qiyunfeng-create
2 天以前 5f00696dfb25bc90034448ceb634ed1ef256681a
Merge branch 'master' of http://182.92.203.7:2001/r/xiehe_website
16个文件已删除
16个文件已添加
1 文件已重命名
29个文件已修改
5323 ■■■■ 已修改文件
package-lock.json 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/book-cover.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/bookStore/feblei.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/default_avatar.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/delete.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/header/dialogLeftImg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/index/bookListBg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/login/boxBg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/login/pageBg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/login/weChartIcon.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/packDown.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/packUp.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/pageHeader/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/teaching/arrow.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/teaching/electronicBooks.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/teaching/paperCopies.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/teaching/sample.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/teaching/teacher.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/identity.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/resource.js 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/tool.js 117 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/toolClass.js 208 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/main.css 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/MapContainer.vue 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sliderImg/component/verify.vue 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sliderImg/img/refresh.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sliderImg/img/right.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sliderImg/img/update@3.5x.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sliderImg/sliderImg.css 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sliderImg/sliderImg.js 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/headerPage.vue 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/login.vue 845 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugin/axios/index.ts 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/index.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/index.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/breadcrumb.ts 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.js 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/aboutUs/index.vue 378 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bookStore/detail.vue 593 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bookStore/index.vue 383 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/classHome.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/components/headerPage.vue 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/index.vue 135 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/jobManage.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/studentJob.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/talkDetail.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/talkingPoint.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/teachInteraction.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/classManage/teachingPlan.vue 516 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/educationalPublishing/index.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/index.vue 327 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/activeCode.vue 84 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/course.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/index.vue 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/myApply.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/myBook.vue 102 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/myCart.vue 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/myCollection.vue 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/myOrder.vue 114 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personalCenter/userInfo.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -8,6 +8,7 @@
      "name": "xiehe",
      "version": "0.0.0",
      "dependencies": {
        "@amap/amap-jsapi-loader": "^1.0.1",
        "axios": "^1.11.0",
        "element-plus": "^2.10.7",
        "less": "^4.4.0",
@@ -15,6 +16,7 @@
        "pinia": "^3.0.3",
        "spark-md5": "^3.0.2",
        "vue": "^3.5.18",
        "vue-baidu-map-3x": "^1.0.40",
        "vue-clipboard3": "^2.0.0",
        "vue-router": "^4.5.1"
      },
@@ -27,6 +29,12 @@
      "engines": {
        "node": "^20.19.0 || >=22.12.0"
      }
    },
    "node_modules/@amap/amap-jsapi-loader": {
      "version": "1.0.1",
      "resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==",
      "license": "MIT"
    },
    "node_modules/@ampproject/remapping": {
      "version": "2.3.0",
@@ -1621,6 +1629,12 @@
        }
      }
    },
    "node_modules/@yangjianfei/bmaplib.lushu": {
      "version": "1.0.0",
      "resolved": "https://registry.npmmirror.com/@yangjianfei/bmaplib.lushu/-/bmaplib.lushu-1.0.0.tgz",
      "integrity": "sha512-qZVijbgUgNs6tsP1muS67x0XzE5fJ3kFireouDvXO3bUYVV6XbpjZXksQTsggihLMIEvC1DO9GS9vVF8CnEeqQ==",
      "license": "MIT"
    },
    "node_modules/ansis": {
      "version": "4.1.0",
      "resolved": "https://registry.npmmirror.com/ansis/-/ansis-4.1.0.tgz",
@@ -1660,6 +1674,39 @@
      "funding": {
        "url": "https://github.com/sponsors/antfu"
      }
    },
    "node_modules/bmaplib.curveline": {
      "version": "1.0.0",
      "resolved": "https://registry.npmmirror.com/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz",
      "integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q==",
      "license": "MIT"
    },
    "node_modules/bmaplib.distancetool": {
      "version": "1.0.2",
      "resolved": "https://registry.npmmirror.com/bmaplib.distancetool/-/bmaplib.distancetool-1.0.2.tgz",
      "integrity": "sha512-EvxMnQRH6xM036zx5OLPyTg5tMCTbFBuGTTHOtExLy2/T0X6v5Va0YE7c3IPm/a/Eo5V/ynYpOLOLZbRY8ccyA==",
      "license": "MIT"
    },
    "node_modules/bmaplib.heatmap": {
      "version": "1.0.4",
      "resolved": "https://registry.npmmirror.com/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz",
      "integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q==",
      "license": "MIT"
    },
    "node_modules/bmaplib.markerclusterer": {
      "version": "1.0.13",
      "resolved": "https://registry.npmmirror.com/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz",
      "integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==",
      "license": "MIT",
      "dependencies": {
        "bmaplib.texticonoverlay": "^1.0.2"
      }
    },
    "node_modules/bmaplib.texticonoverlay": {
      "version": "1.0.2",
      "resolved": "https://registry.npmmirror.com/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz",
      "integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg==",
      "license": "MIT"
    },
    "node_modules/browserslist": {
      "version": "4.25.2",
@@ -3117,7 +3164,8 @@
    "node_modules/tiny-emitter": {
      "version": "2.1.0",
      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
      "license": "MIT"
    },
    "node_modules/tinyglobby": {
      "version": "0.2.14",
@@ -3426,6 +3474,25 @@
        }
      }
    },
    "node_modules/vue-baidu-map-3x": {
      "version": "1.0.40",
      "resolved": "https://registry.npmmirror.com/vue-baidu-map-3x/-/vue-baidu-map-3x-1.0.40.tgz",
      "integrity": "sha512-Rq3g1KNsNztkuX3SJIuCpy6HE3xHVX8ySgqS2xC3jut/hvVr5kFBS0Nu7uYppk3xYVz69S1JFxU8WUI0Xftpyg==",
      "license": "MIT",
      "dependencies": {
        "@yangjianfei/bmaplib.lushu": "^1.0.0",
        "bmaplib.curveline": "^1.0.0",
        "bmaplib.distancetool": "^1.0.2",
        "bmaplib.heatmap": "^1.0.4",
        "bmaplib.markerclusterer": "^1.0.13",
        "tiny-emitter": "^2.1.0",
        "vue": "^3.2.25",
        "vue-router": "^4.0.14"
      },
      "peerDependencies": {
        "vue": "^3.2.25"
      }
    },
    "node_modules/vue-clipboard3": {
      "version": "2.0.0",
      "resolved": "https://registry.npmmirror.com/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz",
@@ -3503,6 +3570,11 @@
    }
  },
  "dependencies": {
    "@amap/amap-jsapi-loader": {
      "version": "1.0.1",
      "resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
    },
    "@ampproject/remapping": {
      "version": "2.3.0",
      "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -4502,6 +4574,11 @@
        }
      }
    },
    "@yangjianfei/bmaplib.lushu": {
      "version": "1.0.0",
      "resolved": "https://registry.npmmirror.com/@yangjianfei/bmaplib.lushu/-/bmaplib.lushu-1.0.0.tgz",
      "integrity": "sha512-qZVijbgUgNs6tsP1muS67x0XzE5fJ3kFireouDvXO3bUYVV6XbpjZXksQTsggihLMIEvC1DO9GS9vVF8CnEeqQ=="
    },
    "ansis": {
      "version": "4.1.0",
      "resolved": "https://registry.npmmirror.com/ansis/-/ansis-4.1.0.tgz",
@@ -4532,6 +4609,34 @@
      "version": "2.5.0",
      "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.5.0.tgz",
      "integrity": "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ=="
    },
    "bmaplib.curveline": {
      "version": "1.0.0",
      "resolved": "https://registry.npmmirror.com/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz",
      "integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q=="
    },
    "bmaplib.distancetool": {
      "version": "1.0.2",
      "resolved": "https://registry.npmmirror.com/bmaplib.distancetool/-/bmaplib.distancetool-1.0.2.tgz",
      "integrity": "sha512-EvxMnQRH6xM036zx5OLPyTg5tMCTbFBuGTTHOtExLy2/T0X6v5Va0YE7c3IPm/a/Eo5V/ynYpOLOLZbRY8ccyA=="
    },
    "bmaplib.heatmap": {
      "version": "1.0.4",
      "resolved": "https://registry.npmmirror.com/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz",
      "integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q=="
    },
    "bmaplib.markerclusterer": {
      "version": "1.0.13",
      "resolved": "https://registry.npmmirror.com/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz",
      "integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==",
      "requires": {
        "bmaplib.texticonoverlay": "^1.0.2"
      }
    },
    "bmaplib.texticonoverlay": {
      "version": "1.0.2",
      "resolved": "https://registry.npmmirror.com/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz",
      "integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg=="
    },
    "browserslist": {
      "version": "4.25.2",
@@ -5637,6 +5742,21 @@
        "@vue/shared": "3.5.18"
      }
    },
    "vue-baidu-map-3x": {
      "version": "1.0.40",
      "resolved": "https://registry.npmmirror.com/vue-baidu-map-3x/-/vue-baidu-map-3x-1.0.40.tgz",
      "integrity": "sha512-Rq3g1KNsNztkuX3SJIuCpy6HE3xHVX8ySgqS2xC3jut/hvVr5kFBS0Nu7uYppk3xYVz69S1JFxU8WUI0Xftpyg==",
      "requires": {
        "@yangjianfei/bmaplib.lushu": "^1.0.0",
        "bmaplib.curveline": "^1.0.0",
        "bmaplib.distancetool": "^1.0.2",
        "bmaplib.heatmap": "^1.0.4",
        "bmaplib.markerclusterer": "^1.0.13",
        "tiny-emitter": "^2.1.0",
        "vue": "^3.2.25",
        "vue-router": "^4.0.14"
      }
    },
    "vue-clipboard3": {
      "version": "2.0.0",
      "resolved": "https://registry.npmmirror.com/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz",
package.json
@@ -13,6 +13,7 @@
    "format": "prettier --write src/"
  },
  "dependencies": {
    "@amap/amap-jsapi-loader": "^1.0.1",
    "axios": "^1.11.0",
    "element-plus": "^2.10.7",
    "less": "^4.4.0",
@@ -21,6 +22,7 @@
    "spark-md5": "^3.0.2",
    "vue": "^3.5.18",
    "vue-clipboard3": "^2.0.0",
    "vue-baidu-map-3x": "^1.0.40",
    "vue-router": "^4.5.1"
  },
  "devDependencies": {
src/assets/images/book-cover.png
src/assets/images/bookStore/feblei.png
src/assets/images/default_avatar.png
Binary files differ
src/assets/images/delete.png
Binary files differ
src/assets/images/header/dialogLeftImg.png
src/assets/images/index/bookListBg.png
Binary files differ
src/assets/images/login/boxBg.png
Binary files differ
src/assets/images/login/pageBg.png
Binary files differ
src/assets/images/login/weChartIcon.png
Binary files differ
src/assets/images/packDown.png
Binary files differ
src/assets/images/packUp.png
Binary files differ
src/assets/images/pageHeader/logo.png
Binary files differ
src/assets/images/teaching/arrow.png
Binary files differ
src/assets/images/teaching/electronicBooks.png
Binary files differ
src/assets/images/teaching/paperCopies.png
Binary files differ
src/assets/images/teaching/sample.png
Binary files differ
src/assets/images/teaching/teacher.png
Binary files differ
src/assets/js/middleGround/api/identity.js
@@ -34,6 +34,20 @@
    })
  },
  getSlideCaptchaImage(options) {
    return request('/identity/GetSlideCaptchaImage', {
      method: 'POST',
      data: options || {},
    })
  },
  // 验证滑动验证码
  validSlideCaptcha(options) {
    return request('/identity/ValidSlideCaptcha', {
      method: 'POST',
      data: options || {},
    })
  },
  // 通过手机号注册用户
  registerAppUserWithPhone(data) {
    return request({
src/assets/js/middleGround/api/resource.js
@@ -30,7 +30,7 @@
    coverSize,
    itemIdArr,
    SysType,
    tourism_isHighQualityResources,
    isHighQualityResources,
  }) => {
    if (!path) return Promise.reject("接口请求必要参数不能为空!");
@@ -71,9 +71,9 @@
    };
    if (itemIdArr) query["Id"] = itemIdArr;
    if (SysType) query["SysType="] = [`${SysType}`];
    if (tourism_isHighQualityResources)
      query["tourism_isHighQualityResources="] = [
        `${tourism_isHighQualityResources}`,
    if (isHighQualityResources)
      query["isHighQualityResources="] = [
        `${isHighQualityResources}`,
      ];
    if (itemId) query["Id="] = [`${itemId}`];
    if (itemIds) query["Id="] = itemIds;
@@ -121,26 +121,26 @@
    if (params.length > 0) {
      let data = {
        "||Name": [...params],
        "||tourism_content*": [...params],
        "||tourism_workflow*": [...params],
        "||tourism_notes*": [...params],
        "||tourism_caseIndex*": [...params],
        "||tourism_basicCase*": [...params],
        "||tourism_judgmentAndReasons*": [...params],
        "||tourism_legalIssuesInvolvedInThisCase*": [...params],
        "||tourism_referenceAnswerAndLegalAnalysis*": [...params],
        "||tourism_case*": [...params],
        "||tourism_clause*": [...params],
        "||tourism_unscramble*": [...params],
        "||tourism_specialRemind*": [...params],
        "||tourism_fiction*": [...params],
        "||tourism_authorityNature*": [...params],
        "||tourism_authorityGist*": [...params],
        "||tourism_penaltyGist*": [...params],
        "||tourism_penaltyTerms*": [...params],
        "||tourism_penaltyType*": [...params],
        "||tourism_remarksNote*": [...params],
        "||tourism_keyword*": [...params],
        "||content*": [...params],
        "||workflow*": [...params],
        "||notes*": [...params],
        "||caseIndex*": [...params],
        "||basicCase*": [...params],
        "||judgmentAndReasons*": [...params],
        "||legalIssuesInvolvedInThisCase*": [...params],
        "||referenceAnswerAndLegalAnalysis*": [...params],
        "||case*": [...params],
        "||clause*": [...params],
        "||unscramble*": [...params],
        "||specialRemind*": [...params],
        "||fiction*": [...params],
        "||authorityNature*": [...params],
        "||authorityGist*": [...params],
        "||penaltyGist*": [...params],
        "||penaltyTerms*": [...params],
        "||penaltyType*": [...params],
        "||remarksNote*": [...params],
        "||keyword*": [...params],
      };
      Object.assign(queryBody, data);
    } else {
@@ -155,7 +155,7 @@
      let data = {
        Path: [
          {
            Repository: "tourism_tourismLawsAndRegulationsDatabase",
            Repository: "tourismLawsAndRegulationsDatabase",
            Path: path,
          },
        ],
src/assets/js/middleGround/tool.js
@@ -1,7 +1,7 @@
import { requestCtx, appId } from '@/assets/js/config.js'
// import defaultImg from '@/assets/images/default-book-img.png'
// import defaultBookFair from '@/assets/images/default-bookFair.png'
// import bookCover from '@/assets/images/book-cover.png'
import bookCover from '@/assets/images/book-cover.png'
// import defaultPub from '@/assets/images/math/default-pub.png'
// import defaultAudio from '@/assets/images/math/default-audio.png'
import moment from 'moment'
@@ -13,7 +13,7 @@
  storeInfo,
  repositoryInfo,
  coverSize,
  handelEBooK
  handelEBooK,
}) {
  const dataList = []
  for (let i = 0; i < datas.length; i++) {
@@ -78,7 +78,7 @@
      subProductCount: parseInt(item.datas.SubProductCount),
      ..._fields,
      datas: item.datas,
      subDatas
      subDatas,
    }
    // 统一处理价格
@@ -88,7 +88,7 @@
        let saleMethod = []
        try {
          saleMethod = obj.cmsDatas[0].datas.find(
            (item) => item.datas.RefCode == 'tourism_accompanyingResources'
            (item) => item.datas.RefCode == 'accompanyingResources',
          ).datas.SaleMethod
          saleMethod = JSON.parse(saleMethod)
        } catch (error) {
@@ -154,22 +154,22 @@
  itemFields,
  handelEBooK,
}) {
  item.fileMap = {};
  let itemFieldsData = [];
  item.fileMap = {}
  let itemFieldsData = []
  for (const key in itemFields) {
    itemFieldsData.push(key);
    itemFieldsData.push(key)
  }
  let fieldsData = [];
  let fieldsData = []
  for (const key in fields) {
    fieldsData.push(key);
    fieldsData.push(key)
  }
  for (let i = 0; i < fieldsData.length; i++) {
    const field = fieldsData[i];
    item.datas[field] = JSON.parse(item.datas[field]);
    const datas = item.datas[field];
    const field = fieldsData[i]
    item.datas[field] = JSON.parse(item.datas[field])
    const datas = item.datas[field]
    if (datas.length > 0) {
      if (datas[0].Value) {
        item[field] = datas[0].Value;
        item[field] = datas[0].Value
        if (datas[0].Data.FileLinkList && datas[0].Data.FileLinkList.length) {
          item.fileMap = {
            ...item.fileMap,
@@ -178,13 +178,13 @@
                return {
                  ...item.File,
                  ...item,
                };
              })
                }
              }),
            ),
          };
          }
        }
      } else if (datas[0].Data) {
        item[field] = datas[0].Data.Value;
        item[field] = datas[0].Data.Value
        if (datas[0].Data.FileLinkList && datas[0].Data.FileLinkList.length) {
          item.fileMap = {
            ...item.fileMap,
@@ -193,84 +193,77 @@
                return {
                  ...item.File,
                  ...item,
                };
              })
                }
              }),
            ),
          };
          }
        }
      }
    }
  }
  // 处理cms资源
  const subDatas = item.subDatas;
  const linkItemsMap = {};
  const subDatas = item.subDatas
  const linkItemsMap = {}
  if (subDatas) {
    for (const sdata of subDatas) {
      const tag = sdata.queryTag;
      const tag = sdata.queryTag
      for (const subItem of sdata.datas) {
        convertCmsItemBase(subItem, coverSize, handelEBooK);
        subItem.fileMap = {};
        convertCmsItemBase(subItem, coverSize, handelEBooK)
        subItem.fileMap = {}
        for (let i = 0; i < itemFieldsData.length; i++) {
          const itemField = itemFieldsData[i];
          const itemField = itemFieldsData[i]
          try {
            subItem.datas[itemField] = JSON.parse(subItem.datas[itemField]);
            subItem.datas[itemField] = JSON.parse(subItem.datas[itemField])
          } catch (error) {
            subItem.datas[itemField] = [];
            subItem.datas[itemField] = []
          }
          const itemDatas = subItem.datas[itemField];
          const itemDatas = subItem.datas[itemField]
          if (itemDatas.length > 0) {
            if (itemDatas[0].Value) {
              subItem[itemField] = itemDatas[0].Value;
              subItem[itemField] = itemDatas[0].Value
              if (itemDatas[0].FileList && itemDatas[0].FileList.length) {
                subItem.fileMap = {
                  ...subItem.fileMap,
                  ...handleLinkFileInfo(itemDatas[0].FileList),
                };
                }
              }
            } else if (itemDatas[0].Data) {
              subItem[itemField] = itemDatas[0].Data.Value;
              if (
                itemDatas[0].Data.FileList &&
                itemDatas[0].Data.FileList.length
              ) {
              subItem[itemField] = itemDatas[0].Data.Value
              if (itemDatas[0].Data.FileList && itemDatas[0].Data.FileList.length) {
                subItem.fileMap = {
                  ...subItem.fileMap,
                  ...handleLinkFileInfo(itemDatas[0].Data.FileList),
                };
                }
              }
            } else if (itemDatas[0].CmsItemData) {
              subItem[itemField] = itemDatas[0].CmsItemData.Value;
              if (
                itemDatas[0].CmsItemData.FileList &&
                itemDatas[0].CmsItemData.FileList.length
              ) {
              subItem[itemField] = itemDatas[0].CmsItemData.Value
              if (itemDatas[0].CmsItemData.FileList && itemDatas[0].CmsItemData.FileList.length) {
                subItem.fileMap = {
                  ...subItem.fileMap,
                  ...handleLinkFileInfo(itemDatas[0].CmsItemData.FileList),
                };
                }
              }
            }
          }
        }
        if (subItem.productLinkInfo && subItem.productLinkInfo.length) {
          let itemProductLinkInfo = subItem.productLinkInfo.find(citem => citem.Name == item.datas.Name)
          let itemProductLinkInfo = subItem.productLinkInfo.find(
            (citem) => citem.Name == item.datas.Name,
          )
          subItem.productLinkPath =
            itemProductLinkInfo.LinkPath +
            "\\" +
            itemProductLinkInfo.CmsItemId;
            itemProductLinkInfo.LinkPath + '\\' + itemProductLinkInfo.CmsItemId
        }
        if (subItem.linkInfo && subItem.linkInfo.length)
          subItem.linkPath =
            subItem.linkInfo[0].LinkPath + "\\" + subItem.linkInfo[0].CmsItemId;
          subItem.linkPath = subItem.linkInfo[0].LinkPath + '\\' + subItem.linkInfo[0].CmsItemId
      }
      linkItemsMap[tag] = sdata.datas;
      linkItemsMap[tag] = sdata.datas
    }
  }
  convertCmsItemBase(item, coverSize, handelEBooK);
  item.idPath = path + "\\" + item.id;
  item.subItems = linkItemsMap;
  return item;
  convertCmsItemBase(item, coverSize, handelEBooK)
  item.idPath = path + '\\' + item.id
  item.subItems = linkItemsMap
  return item
}
const handleLinkFileInfo = (linkList) => {
@@ -287,7 +280,7 @@
      size: linkItem.Size,
      // metaData: JSON.parse(linkItem.MetaData ?? "{}"),
      order: linkItem.Order,
      protectType: linkItem.ProtectType
      protectType: linkItem.ProtectType,
    }
  }
  return linkFileMap
@@ -309,9 +302,9 @@
  item.linkStoreId = parseInt(item.datas.LinkStore)
  item.linkRepoId = item.datas.LinkRepository
  item.childrenCount = parseInt(item.datas.ChildrenCount ?? '0')
  ;(item.childrenFolderCount = parseInt(item.datas.ChildrenFolderCount ?? '0')),
  ;((item.childrenFolderCount = parseInt(item.datas.ChildrenFolderCount ?? '0')),
    (item.childrenChannelCount = parseInt(item.datas.ChildrenChannelCount ?? '0')),
    (item.linkId = parseInt(item.datas.LinkId))
    (item.linkId = parseInt(item.datas.LinkId)))
  item.linkOrg = JSON.parse(item.datas.LinkOrg ?? '[]')[0]
  item.linkDepartment = JSON.parse(item.datas.LinkDepartment ?? '[]')[0]
  item.linkInfo = JSON.parse(item.datas.LinkInfo ?? '[]')
@@ -328,7 +321,7 @@
    if (handelEBooK) {
      // 获取随书资源的销售方式
      let saleMethod = item.cmsDatas[0].datas.find(
        (item) => item.refCode == 'tourism_accompanyingResources'
        (item) => item.refCode == 'accompanyingResources',
      ).saleMethod
      if (saleMethod && saleMethod.length > 0) {
        Object.keys(saleMethod[0]).map((key) => {
@@ -411,10 +404,10 @@
  if (md5) {
    src = requestCtx + `/file/GetPreViewImage?md5=${md5}`
  } else {
    if(storeInfo == `defaultGoodsStore${appId}`){
      return bookCover;
    }else{
      return ""
    if (storeInfo == `defaultGoodsStore${appId}`) {
      return bookCover
    } else {
      return ''
    }
  }
  if (width && src) src += `&width=${width}`
src/assets/js/toolClass.js
@@ -1,12 +1,7 @@
import SparkMD5 from 'spark-md5'
import {
  getPublicImage
} from '@/assets/js/middleGround/tool.js'
import { getPublicImage } from '@/assets/js/middleGround/tool.js'
import config from './config'
import moment from "moment";
import moment from 'moment'
var tool = {
  secondToTime(second) {
@@ -74,9 +69,8 @@
      .replace(/\.[\d]{3}Z/, '')
    var time = new Date(newDate)
    return time.getTime()
  }
  },
}
//处理表单提交数据
export function worksData(res) {
@@ -101,8 +95,8 @@
      nrr.push({
        linkProtectType: e.linkProtectType,
        linkType: e.linkType,
        md5: e.md5
      })
        md5: e.md5,
      }),
    )
  }
  res.forEach((item) => {
@@ -111,7 +105,7 @@
      order: 0,
      typeFieldId: item.typeField.id,
      sequenceNum: item.config ? JSON.parse(item.config).uuid : '',
      newDataAndFileLinkListRequest: []
      newDataAndFileLinkListRequest: [],
    }
    for (let k in value) {
      if (item.typeField.refCode === k) {
@@ -165,7 +159,7 @@
        id: updateOldData.id,
        typeFieldId: citem.typeField.id,
        sequenceNum: citem.sequenceNum,
        setDataAndFileLinkListRequest: []
        setDataAndFileLinkListRequest: [],
      }
      for (let k in value) {
        if (citem.typeField.refCode === k) {
@@ -174,9 +168,11 @@
            obj.setDataAndFileLinkListRequest = linkList
          } else if (typeof value[k] == 'object' && k == 'region') {
            obj.strValue = value[k]?.join('/')
            obj.setDataAndFileLinkListRequest = [{
              area: value[k]
            }]
            obj.setDataAndFileLinkListRequest = [
              {
                area: value[k],
              },
            ]
          } else {
            obj.strValue = value[k].toString()
          }
@@ -191,7 +187,7 @@
        order: 0,
        typeFieldId: citem.typeField.id,
        sequenceNum: citem.sequenceNum,
        setDataAndFileLinkListRequest: []
        setDataAndFileLinkListRequest: [],
      }
      for (let k in value) {
        if (citem.typeField.refCode === k) {
@@ -210,7 +206,7 @@
  })
  return {
    updateData: arr,
    newData: newArr
    newData: newArr,
  }
}
@@ -298,10 +294,7 @@
// 获取文件
export function getPublicFile(md5, isToken) {
  const {
    tokenKey,
    requestCtx
  } = config
  const { tokenKey, requestCtx } = config
  let src = null
  let token = localStorage.getItem(tokenKey)
  if (md5) {
@@ -316,33 +309,28 @@
  return src
}
export const handleCmsItemListRequestData = (datas, fields, path, storeId, repositoryId) => {
  const dataList = [];
  const dataList = []
  for (let i = 0; i < datas.length; i++) {
    const item = datas[i];
    const _fields = {};
    const _datas = [];
    const item = datas[i]
    const _fields = {}
    const _datas = []
    if (fields != null) {
      for (let fieldKey in fields) {
        // 兼容筛选条件的字段值获取,因为后台筛选和取值只能传一个,都会返回值
        fieldKey = fieldKey.replace(/[!=<>*]/g, '');
        fieldKey = fieldKey.replace(/[!=<>*]/g, '')
        if (item.datas[fieldKey]) {
          let values = [];
          let values = []
          if (typeof item.datas[fieldKey] == 'string') {
            values = JSON.parse(item.datas[fieldKey]);
            values = JSON.parse(item.datas[fieldKey])
          } else {
            values = item.datas[fieldKey];
            values = item.datas[fieldKey]
          }
          if (values ?.length > 0) {
          if (values?.length > 0) {
            // 用字段名处理返回的字段值
            if (values[0].Value) {
              _fields[fieldKey] = values[0].Value;
              values[0].sequenceNum = values[0].SequenceNum;
              _fields[fieldKey] = values[0].Value
              values[0].sequenceNum = values[0].SequenceNum
            }
            // 兼容处理数据返回的key是CmsItemData
            // if (values[0].CmsItemData) {
@@ -350,24 +338,24 @@
            //   values[0].sequenceNum = values[0].CmsItemData.SequenceNum;
            // }
            item.datas[fieldKey] = values[0];
            if (values ?.length > 1) {
              const isFile = values.find((citem) => citem.FileList ?.length > 0);
              const dataItems = deduplicateArray(values, 'FieldId');
            item.datas[fieldKey] = values[0]
            if (values?.length > 1) {
              const isFile = values.find((citem) => citem.FileList?.length > 0)
              const dataItems = deduplicateArray(values, 'FieldId')
              if (!isFile) {
                _datas.push(dataItems[0]);
                _datas.push(dataItems[0])
              } else {
                const customFile = {
                  customFileList: values,
                  name: fieldKey,
                  md5: _fields[fieldKey],
                  FieldId: values[0].FieldId,
                  SequenceNum: values[0].SequenceNum
                };
                _datas.push(customFile);
                  SequenceNum: values[0].SequenceNum,
                }
                _datas.push(customFile)
              }
            } else {
              _datas.push(values[0]);
              _datas.push(values[0])
            }
          }
        }
@@ -375,14 +363,14 @@
    }
    if (item.datas.LogQuery) {
      item.datas.LogQuery = JSON.parse(item.datas.LogQuery);
      item.datas.LogQuery = JSON.parse(item.datas.LogQuery)
    }
    const subDatas = {};
    const subDatas = {}
    if (item.subDatas) {
      for (let subData of item.subDatas) {
        const tag = subData.queryTag.replace('Query', '');
        subDatas[tag] = subData.datas;
        const tag = subData.queryTag.replace('Query', '')
        subDatas[tag] = subData.datas
      }
    }
    dataList.push({
@@ -414,47 +402,48 @@
      linkInfo: item.datas.LinkInfo ? JSON.parse(item.datas.LinkInfo) : [],
      linkPath: item.datas.LinkPath ?? null,
      linkOrg: item.datas.LinkOrg ? JSON.parse(item.datas.LinkOrg) : [],
      linkDepartment: item.datas.LinkDepartment? JSON.parse(item.datas.LinkDepartment) : [],
      linkDepartment: item.datas.LinkDepartment ? JSON.parse(item.datas.LinkDepartment) : [],
      ..._fields,
      datas: item.datas,
      fieldList: _datas,
      subDatas
    });
      subDatas,
    })
  }
  return dataList;
};
  return dataList
}
// type结构处理
export const handleTypeList = (list) => {
  for (let i = 0; i < list.length; i++) {
    const type = list[i];
    const type = list[i]
    try {
      type.cfg = JSON.parse(type.config);
      type.cfg = JSON.parse(type.config)
    } catch (error) {
      type.cfg = null;
      type.cfg = null
    }
    const fieldRefcodeMap = {};
    const tableHeaderFieldList = [];
    const isSearchFieldList = [];
    const isAdvSearchFieldList = [];
    const isFilterFieldList = [];
    const fieldRefcodeMap = {}
    const tableHeaderFieldList = []
    const isSearchFieldList = []
    const isAdvSearchFieldList = []
    const isFilterFieldList = []
    console.log(type, 'type')
    handleType({
      typeFieldList: type.typeLinkList,
      typeFieldList: type.cmsTypeLinks,
      fieldRefcodeMap,
      tableHeaderFieldList,
      isSearchFieldList,
      isAdvSearchFieldList,
      isFilterFieldList
    });
    type.fieldRefcodeMap = fieldRefcodeMap;
    type.tableHeaderFieldList = tableHeaderFieldList;
    type.isSearchFieldList = isSearchFieldList;
    type.isAdvSearchFieldList = isAdvSearchFieldList;
    type.isFilterFieldList = isFilterFieldList;
      isFilterFieldList,
    })
    type.fieldRefcodeMap = fieldRefcodeMap
    type.tableHeaderFieldList = tableHeaderFieldList
    type.isSearchFieldList = isSearchFieldList
    type.isAdvSearchFieldList = isAdvSearchFieldList
    type.isFilterFieldList = isFilterFieldList
  }
  return list;
};
  return list
}
const handleType = ({
  typeFieldList,
@@ -462,34 +451,34 @@
  tableHeaderFieldList,
  isSearchFieldList,
  isAdvSearchFieldList,
  isFilterFieldList
  isFilterFieldList,
}) => {
  for (let i = 0; i < typeFieldList.length; i++) {
    const item = typeFieldList[i];
    const item = typeFieldList[i]
    try {
      item.cfg = JSON.parse(item.config);
      item.cfg = JSON.parse(item.config)
    } catch (error) {
      item.cfg = null;
      item.cfg = null
    }
    if (item.typeField) {
      try {
        item.typeField.cfg = JSON.parse(item.typeField.config);
        item.typeField.cfg = JSON.parse(item.typeField.config)
      } catch (error) {
        item.typeField.cfg = null;
        item.typeField.cfg = null
      }
      fieldRefcodeMap[item.typeField.refCode] = item;
      fieldRefcodeMap[item.typeField.refCode] = item
    }
    if (item.cfg && item.cfg.isColHeader) {
      tableHeaderFieldList.push(item);
      tableHeaderFieldList.push(item)
    }
    if (item.cfg && item.cfg.isSearch) {
      isSearchFieldList.push(item);
      isSearchFieldList.push(item)
    }
    if (item.cfg && item.cfg.isAdvSearch) {
      isAdvSearchFieldList.push(item);
      isAdvSearchFieldList.push(item)
    }
    if (item.cfg && item.cfg.isFilter) {
      isFilterFieldList.push(item);
      isFilterFieldList.push(item)
    }
    if (item.children && item.children.length) {
      handleType({
@@ -498,59 +487,54 @@
        tableHeaderFieldList,
        isSearchFieldList,
        isAdvSearchFieldList,
        isFilterFieldList
      });
        isFilterFieldList,
      })
    }
  }
};
}
//处理树形结构
const handleTreeData = (datas, parent, noTriggerSelect = false) => {
  let parentData = {};
  let parentData = {}
  if (parent) {
    parentData = { ...parent, parent: null };
    parentData = { ...parent, parent: null }
  } else {
    parentData = null;
    parentData = null
  }
  const list = [];
  const list = []
  for (let i = 0; i < datas.length; i++) {
    const data = datas[i];
    const data = datas[i]
    const obj = {
      label: data.name,
      key: parentData ? parentData.key + "_" + i : i + "",
      namePath: parentData ? parentData.namePath + "\\" + data.name : data.name,
      key: parentData ? parentData.key + '_' + i : i + '',
      namePath: parentData ? parentData.namePath + '\\' + data.name : data.name,
      icon: data.icon,
      data: data,
      parent: parentData,
      leaf: false,
      children: [],
    };
    if (data["children"] && data["children"].length) {
      obj.leaf = false;
    }
    if (data['children'] && data['children'].length) {
      obj.leaf = false
      obj.children = handleTreeData(
        data["children"],
        data['children'],
        {
          ...data,
          key: obj.key,
          namePath: obj.namePath,
        },
        i == 0 ? false : true // 如果有子数据处理,只有第一条数据需要展开和回调
      );
        i == 0 ? false : true, // 如果有子数据处理,只有第一条数据需要展开和回调
      )
    } else {
      obj.leaf =
        !data["childrenChannelCount"] || data["childrenChannelCount"] == 0;
      obj.leaf = !data['childrenChannelCount'] || data['childrenChannelCount'] == 0
    }
    list.push(obj);
    list.push(obj)
  }
  console.log(list, "list");
  return list;
};
  console.log(list, 'list')
  return list
}
//获取资源
export default {
  ...tool,
@@ -564,4 +548,4 @@
  handleTypeList,
  handleTreeData,
  // parseHtml,
}
}
src/assets/main.css
@@ -9,6 +9,11 @@
  --el-color-primary-dark-3: #019e58 !important;
}
/* 基础样式 */
*{
  outline: none;
}
/* 居中布局 */
.contentBox {
  width: 1200px;
@@ -174,9 +179,9 @@
  color: #00873C !important;
} */
.el-input-group__append,
.el-input-group__prepend {
  vertical-align: initial !important;
.el-input-group__append, .el-input-group__prepend {
  /* vertical-align: initial !important; */
  /* align-items: stretch !important; */
}
/* 个人中心页面公共样式 */
src/components/MapContainer.vue
New file
@@ -0,0 +1,90 @@
<template>
  <div class="map-container">
    <!-- 地图容器 -->
    <div id="map-container" ref="mapContainer"></div>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader'
// 配置安全密钥(推荐)
window._AMapSecurityConfig = {
  securityJsCode: '4c6cee842f5412a45a781aeaa76e12cc', // 高德控制台获取
}
const mapContainer = ref(null)
const mapInstance = ref(null)
const marker = ref(null)
// 示例地点数据
const location = ref({
  name: '天安门广场',
  address: '北京市东城区长安街',
  position: [116.413823, 39.912052],
})
// 初始化地图
onMounted(() => {
  AMapLoader.load({
    key: '4c6cee842f5412a45a781aeaa76e12cc', // 替换为你的Key
    version: '2.0', // SDK版本
    plugins: ['AMap.Marker', 'AMap.ToolBar', 'AMap.Scale'], // 所需插件
  })
    .then((AMap) => {
      // 创建地图实例
      mapInstance.value = new AMap.Map(mapContainer.value, {
        viewMode: '2D', // 默认使用2D模式
        zoom: 15, // 初始缩放级别
        center: location.value.position, // 初始中心点
      })
      // 添加控件
      mapInstance.value.addControl(new AMap.ToolBar())
      mapInstance.value.addControl(new AMap.Scale())
      // 添加标记点
      marker.value = new AMap.Marker({
        position: location.value.position,
        title: location.value.name,
      })
      mapInstance.value.add(marker.value)
      // 点击标记点显示信息
      marker.value.on('click', () => {
        alert(`您点击了:${location.value.name}`)
      })
    })
    .catch((error) => {
      console.error('地图加载失败:', error)
    })
})
</script>
<style scoped>
.map-container {
  position: relative;
  width: 100%;
  height: 500px;
}
#map-container {
  width: 100%;
  height: 100%;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.location-card {
  position: absolute;
  bottom: 20px;
  left: 20px;
  background: white;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  z-index: 10;
  max-width: 300px;
}
</style>
src/components/sliderImg/component/verify.vue
New file
@@ -0,0 +1,69 @@
<template>
  <div class="container">
    <div id="captcha" style="position: relative"></div>
  </div>
</template>
<script>
export default {
  name: "verify",
  props: {
    msg: String,
    MG: Object,
  },
  data() {
    return {
      code: "",
    };
  },
  mounted() {
    this.getImg();
  },
  methods: {
    getImg() {
      var that = this;
      this.MG.identity.getSlideCaptchaImage().then((res) => {
        try {
          if (res) {
            /* eslint-disable */ // 参数1:当前画布父级元素 参数2:滑动成功函数,返回滑动距离,接口参数前缀,当前盒子内子元素及方法  参数3:滑动失败函数返回滑动距离,接口参数前缀  参数4:通过接口获取到的图片以及宽高比  参数5:当前页面的this
            jigsaw.init(
              document.getElementById("captcha"),
              function (left, prefix, objCustom) {
                const data = {
                  captcha: prefix + left,
                };
                that.MG.identity.validSlideCaptcha(data).then((res) => {
                  if (res && res.result == "验证成功") {
                    that.code = res.code;
                    console.log(res, "this.code");
                    document.getElementById("msg").innerHTML = res.result;
                    objCustom.addClass(
                      objCustom.sliderContainer,
                      "sliderContainer_success"
                    );
                    that.$emit("loginImgVerify", res.code);
                  } else {
                    document.getElementById("msg").innerHTML =
                      res.result + ",点击右上角刷新再试一次";
                    objCustom.addClass(
                      objCustom.sliderContainer,
                      "sliderContainer_fail"
                    );
                  }
                });
              },
              function (left, prefix) {
                console.log(left, prefix, "fail");
              },
              res, // 图片参数
              that
            );
          }
        } catch (error) {
          console.log(error);
        }
      });
    },
  },
};
</script>
src/components/sliderImg/img/refresh.png
src/components/sliderImg/img/right.jpg
src/components/sliderImg/img/update@3.5x.png
src/components/sliderImg/sliderImg.css
New file
@@ -0,0 +1,167 @@
.container {
  max-width: 400px;
  width: auto;
  margin: auto;
  overflow: hidden;
}
input {
  display: block;
  width: 290px;
  line-height: 40px;
  padding: 10px;
  box-sizing: border-box;
  outline: none;
  border: 1px solid #c8cccf;
  border-radius: 4px;
  color: #6a6f77;
}
#msg {
  position: absolute;
  bottom: 60px;
  left: 0;
  width: 100%;
  background-color: rgba(0, 0, 0, 0.3);
  line-height: 40px;
  font-size: 14px;
  color: #fff;
  text-align: center;
  z-index: 999;
}
.msgError {
  color: #ff4c05 !important;
}
.msgSuccess {
  color: #52ccba !important;
}
/* a:link,
a:visited,
a:hover,
a:active {
  margin-left: 100px;
  color: #0366d6;
} */
.block {
  position: absolute;
  left: 0;
  top: 0;
}
.sliderContainer {
  position: relative;
  text-align: center;
  width: 400px;
  height: 40px;
  line-height: 40px;
  margin-top: 15px;
  background: #f7f9fa;
  color: #45494c;
  border: 1px solid #e4e7eb;
}
.sliderContainer_active .slider {
  height: 38px;
  top: -1px;
  border: 1px solid #1991fa;
}
.sliderContainer_active .sliderMask {
  height: 38px;
  border-width: 1px;
}
.sliderContainer_success .slider {
  height: 38px;
  top: -1px;
  border: 1px solid #52ccba;
  background-color: #52ccba !important;
}
.sliderContainer_success .sliderMask {
  height: 38px;
  border: 1px solid #52ccba;
  background-color: #d2f4ef;
}
.sliderContainer_success .sliderIcon {
  background-position: 0 -40px !important;
}
.sliderContainer_fail .slider {
  height: 38px;
  top: -1px;
  border: 1px solid #f57a7a;
  background-color: #f57a7a !important;
}
.sliderContainer_fail .sliderMask {
  height: 38px;
  border: 1px solid #f57a7a;
  background-color: #fce1e1;
}
.sliderContainer_fail .sliderIcon {
  background-position: 0 -83px !important;
}
.sliderContainer_active .sliderText,
.sliderContainer_success .sliderText,
.sliderContainer_fail .sliderText {
  display: none;
}
.sliderMask {
  position: absolute;
  left: 0;
  top: 0;
  height: 40px;
  border: 0 solid #1991fa;
  background: #d1e9fe;
}
.slider {
  position: absolute;
  top: 0;
  left: 0;
  width: 40px;
  height: 40px;
  background: #fff;
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.1);
  cursor: pointer;
  transition: background 0.2s linear;
}
.slider:hover {
  background: #1991fa;
}
.slider:hover .sliderIcon {
  background-position: 0 -40px;
}
.sliderIcon {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: url("./img/right.jpg");
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: center;
}
.refreshIcon {
  position: absolute;
  right: 5px;
  top: 5px;
  width: 25px;
  height: 25px;
  cursor: pointer;
  background: url("./img//refresh.png");
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: center;
  z-index: 1;
}
src/components/sliderImg/sliderImg.js
New file
@@ -0,0 +1,262 @@
(function (window) {
  let l = 50, // 滑块边长
    r = 0, // 滑块半径
    w = 300, // canvas宽度
    h = 150, // canvas高度
    PI = Math.PI;
  let L = l + r * 2; // 滑块实际边长
  function createCanvas(width, height) {
    const canvas = createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    return canvas;
  }
  function createImg(onload, info) {
    const img = createElement("img");
    img.crossOrigin = "Anonymous";
    img.onload = onload;
    img.onerror = () => {
      img.src = getRandomImg(info.backgroundImage);
    };
    img.src = getRandomImg(info.backgroundImage);
    return img;
  }
  function createImg2(onload, info) {
    const block = createElement("img");
    block.crossOrigin = "Anonymous";
    block.onload = onload;
    block.onerror = () => {
      block.src = getRandomImg(info.frontImage);
    };
    block.src = getRandomImg(info.frontImage);
    return block;
  }
  function createElement(tagName) {
    return document.createElement(tagName);
  }
  function addClass(tag, className) {
    tag.classList.add(className);
  }
  function removeClass(tag, className) {
    tag.classList.remove(className);
  }
  function getRandomImg(val) {
    return val;
  }
  function sum(x, y) {
    return x + y;
  }
  function square(x) {
    return x * x;
  }
  function clear(obj) {
    obj.canvasCtx.clearRect(0, 0, w, h);
    obj.blockCtx.clearRect(0, 0, w, h);
    obj.block.width = w;
    document.getElementById("msg").innerHTML = null;
    document.getElementById("captcha").innerHTML = null;
  }
  class jigsaw {
    constructor(el, success, fail, info, parent) {
      this.el = el;
      this.success = success;
      this.fail = fail;
      this.info = info;
      this.parent = parent;
    }
    init() {
      if (this.info) {
        const { backgroundHeight, backgroundWidth, frontHeight, frontWidth } =
          this.info;
        l = frontHeight;
        r = 0;
        w = backgroundWidth;
        h = backgroundHeight;
        L = frontWidth;
      }
      this.initDOM();
      this.initImg();
      this.bindEvents();
    }
    initDOM() {
      const canvas = createCanvas(w, h); // 画布
      const block = canvas.cloneNode(true); // 滑块
      const msg = createElement("div");
      const sliderContainer = createElement("div");
      const refreshIcon = createElement("div");
      const sliderMask = createElement("div");
      const slider = createElement("div");
      const sliderIcon = createElement("span");
      const text = createElement("span");
      block.className = "block";
      msg.id = "msg";
      sliderContainer.className = "sliderContainer";
      refreshIcon.className = "refreshIcon";
      sliderMask.className = "sliderMask";
      slider.className = "slider";
      sliderIcon.className = "sliderIcon";
      text.innerHTML = "向右滑动滑块填充拼图";
      text.className = "sliderText";
      const el = this.el;
      el.appendChild(canvas);
      el.appendChild(refreshIcon);
      el.appendChild(block);
      el.appendChild(msg);
      slider.appendChild(sliderIcon);
      sliderMask.appendChild(slider);
      sliderContainer.appendChild(sliderMask);
      sliderContainer.appendChild(text);
      el.appendChild(sliderContainer);
      Object.assign(this, {
        canvas,
        block,
        sliderContainer,
        refreshIcon,
        slider,
        sliderMask,
        sliderIcon,
        text,
        msg,
        canvasCtx: canvas.getContext("2d"),
        blockCtx: block.getContext("2d"),
        addClass,
        clear,
      });
    }
    initImg() {
      const block = createImg2(() => {
        this.blockCtx.drawImage(block, 0, 0, w, h);
      }, this.info);
      const img = createImg(() => {
        this.canvasCtx.drawImage(img, 0, 0, w, h);
      }, this.info);
      this.img = img;
    }
    clean() {
      this.canvasCtx.clearRect(0, 0, w, h);
      this.blockCtx.clearRect(0, 0, w, h);
      this.block.width = w;
    }
    bindEvents() {
      this.el.onselectstart = () => false;
      this.refreshIcon.onclick = () => {
        this.reset();
      };
      let originX,
        originY,
        trail = [],
        isMouseDown = false;
      var that = this;
      var handleDragStart = function (e) {
        originX = e.clientX || e.touches[0].clientX;
        originY = e.clientY || e.touches[0].clientY;
        // (originX = e.x), (originY = e.y);
        isMouseDown = true;
      };
      var handleDragMove = function (e) {
        if (!isMouseDown) return false;
        var eventX = e.clientX || e.touches[0].clientX;
        var eventY = e.clientY || e.touches[0].clientY;
        const moveX = eventX - originX;
        const moveY = eventY - originY;
        if (moveX < 0 || moveX + 38 >= w) return false;
        that.slider.style.left = moveX + "px";
        var blockLeft = ((w - 40 - 20) / (w - 40)) * moveX;
        that.block.style.left = blockLeft + "px";
        addClass(that.sliderContainer, "sliderContainer_active");
        that.sliderMask.style.width = moveX + "px";
        console.log(that.sliderMask.offsetLeft, 4545);
        trail.push(moveY);
      };
      var handleDragEnd = function (e) {
        if (!isMouseDown) return false;
        isMouseDown = false;
        var eventX = e.clientX || e.changedTouches[0].clientX;
        if (eventX == originX) return false;
        removeClass(that.sliderContainer, "sliderContainer_active");
        that.trail = trail;
        const { left } = that.verify();
        const { prefix } = that.info;
        if (left && prefix) {
          that.success(left, prefix, that);
        } else {
          addClass(that.sliderContainer, "sliderContainer_fail");
          that.fail && that.fail(left, prefix);
          setTimeout(() => {
            that.reset();
          }, 1000);
        }
      };
      this.slider.addEventListener("mousedown", handleDragStart);
      this.slider.addEventListener("touchstart", handleDragStart);
      document.addEventListener("mousemove", handleDragMove);
      document.addEventListener("touchmove", handleDragMove);
      document.addEventListener("mouseup", handleDragEnd);
      document.addEventListener("touchend", handleDragEnd);
      document.addEventListener("mousedown", function () {
        return false;
      });
      document.addEventListener("touchstart", function () {
        return false;
      });
      // this.slider.addEventListener("mousedown");
      // document.addEventListener("mousemove");
      // document.addEventListener("mouseup");
    }
    verify() {
      const arr = this.trail; // 拖动时y轴的移动距离
      const average = arr.reduce(sum) / arr.length; // 平均值
      const deviations = arr.map((x) => x - average); // 偏差数组
      const stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length); // 标准差
      const left = parseInt(this.block.style.left);
      return {
        // spliced: Math.abs(left - this.x) < 10,
        // TuringTest: average !== stddev, // 只是简单的验证拖动轨迹,相等时一般为0,表示可能非人为操作
        left,
        // x: this.x,
      };
    }
    reset() {
      this.sliderContainer.className = "sliderContainer";
      this.slider.style.left = 0;
      this.block.style.left = 0;
      this.sliderMask.style.width = 0;
      clear(this);
      // this.initImg();
      this.parent.getImg();
      console.log(this.parent);
    }
  }
  window.jigsaw = {
    init: function (element, success, fail, info, callback) {
      new jigsaw(element, success, fail, info, callback).init();
    },
  };
})(window);
src/layout/components/headerPage.vue
@@ -7,7 +7,7 @@
            () => {
              $router.push({
                path: '/home',
              })
              });
            }
          "
          src="@/assets/images/xiehe/home/Group_303.png"
@@ -27,44 +27,37 @@
            <a
              @click="
                () => {
                  $router.push({
                    path: '/register',
                  })
                  console.log(loginRef.value);
                  loginRef.logIn();
                }
              "
              >注册</a
            >
            |
            <a
              @click="
                () => {
                  $router.push({
                    path: '/login',
                    query: {
                      redirectPath: $route.fullPath,
                    },
                  })
                }
              "
              >登录</a
              >注册/登录</a
            >
          </div>
          <div v-else class="userInfoBox">
            <el-dropdown @command="handleCommand">
              <span style="cursor: pointer">欢迎您,{{ userInfo.name }}!</span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item icon="el-icon-user" command="gotoPersonalCenter"
                  >个人中心</el-dropdown-item
                >
                <el-dropdown-item icon="el-icon-switch-button" command="logout"
                  >退出登录</el-dropdown-item
                >
              </el-dropdown-menu>
              <span class="el-dropdown-link">
                欢迎您,{{ userStore?.userInfo.name }}!
                <el-icon class="el-icon--right">
                  <arrow-down />
                </el-icon>
              </span>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item icon="el-icon-user" command="gotoPersonalCenter"
                    >个人中心</el-dropdown-item
                  >
                  <el-dropdown-item icon="el-icon-switch-button" command="logout"
                    >退出登录</el-dropdown-item
                  >
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </div>
      </div>
    </div>
    <login ref="loginRef"></login>
    <div class="contentBox navBox" v-show="!hideNav">
      <div
        :class="{
@@ -82,8 +75,15 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { Search } from '@element-plus/icons-vue'
import login from "./login.vue";
import { onMounted, ref } from "vue";
import { Search } from "@element-plus/icons-vue";
import { useUserStore } from "@/store";
import { useRouter } from "vue-router";
const userStore = useUserStore();
const router = useRouter();
const loginRef = ref();
const props = defineProps({
  hideSerch: {
    type: Boolean,
@@ -93,32 +93,51 @@
    type: Boolean,
    default: false,
  },
})
});
let searchKey = ref('')
let userInfo = ref('')
let searchKey = ref("");
let userInfo = ref("");
const navData = ref([
  {
    name: '首页',
    path: '/home',
    name: "首页",
    path: "/home",
  },
  {
    name: '教育出版',
    path: '/bookStore',
    name: "教育出版",
    path: "/bookStore",
  },
  {
    name: '读者服务',
    path: '/teachingServices',
    name: "读者服务",
    path: "/teachingServices",
  },
  {
    name: '关于我们',
    path: '/aboutUs',
    name: "关于我们",
    path: "/aboutUs",
  },
])
]);
const gotoSearch = () => {}
const handleCommand = () => {}
const gotoPage = () => {}
onMounted(() => {
  userInfo.value = userStore.userInfo;
  console.log(userInfo.value, "userInfo");
});
const gotoSearch = () => {};
const handleCommand = (item) => {
  if (item === "gotoPersonalCenter") {
    router.push({
      path: "/personalCenter",
    });
  }
  if (item === "logout") {
    localStorage.clear();
    router.push({
      path: "/home",
    });
  }
};
const gotoPage = (item) => {
  router.push(item.path);
};
</script>
<style lang="less" scoped>
@@ -134,17 +153,11 @@
    p {
      float: left;
    }
    .loginInfoBox {
      float: right;
      .loginBtnBox {
        a {
          cursor: pointer;
          text-decoration: none;
          color: inherit;
          margin: 0 4px;
        }
      }
    }
  }
  .loginInfoBox {
    width: 200px;
    margin-left: 20px;
  }
  .logoBox {
    padding: 25px 0;
@@ -162,9 +175,9 @@
      width: 670px;
      float: right;
      padding-right: 10px;
      line-height: 66px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      .searchItem {
        width: 120px;
        vertical-align: initial;
src/layout/components/login.vue
New file
@@ -0,0 +1,845 @@
<template>
  <el-dialog
    align-center
    append-to-body
    v-model="dialogFormVisible"
    @close="closeDialog"
    @open="openDialog"
    class="fansdialog"
  >
    <div style="display: flex; justify-content: space-around">
      <el-image :src="dialogLeftImg" class="leftImg" />
      <div class="logIn">
        <div class="signUpTitle" v-if="flag == 'logIn'">
          <ul>
            <li
              @click="signUpWay = 'authSignUp'"
              :style="{
                color: signUpWay == 'authSignUp' ? '#144941' : '#545C63',
              }"
            >
              手机号登录
            </li>
            <li>|</li>
            <li
              @click="wechatLoginOpen"
              :style="{ color: signUpWay == 'wechat' ? '#144941' : '#545C63' }"
            >
              微信登录
            </li>
          </ul>
        </div>
        <div v-else style="text-align: center; color: #144941">注册</div>
        <div
          class="singUpPhone"
          v-if="signUpWay === 'phone' || 'authSignUp'"
          :style="{ height: signUpWay == 'findPassword' ? '450px' : '400px' }"
        >
          <el-form
            :model="passFormData"
            v-if="signUpWay === 'phone' || 'authSignUp'"
            ref="passFormRef"
            @keyup.enter="signInSystem(passFormRef)"
          >
            <el-form-item
              v-if="signUpWay !== 'findPassword'"
              :rules="[
                { min: 11, max: 11, message: '请输入11位电话号码' },
                {
                  validator: (_, value, callback) => {
                    if (
                      !/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(
                        value
                      )
                    ) {
                      callback('请输入11位电话号码');
                    } else {
                      callback();
                    }
                  },
                },
              ]"
              prop="telNumber"
            >
              <el-input
                v-model="passFormData.telNumber"
                placeholder="请输入手机号"
                size="large"
              >
                <template #prepend>
                  <el-select
                    v-model="select"
                    placeholder="Select"
                    style="width: 110px"
                    class="selectPhone"
                  >
                    <el-option label="中国+86" value="86" />
                  </el-select>
                </template>
              </el-input>
            </el-form-item>
            <el-form-item>
              <el-button class="yanzhengBtn" @click="sliderImgDialogVisable = true"
                >验证</el-button
              >
            </el-form-item>
            <el-form-item
              v-if="signUpWay === 'authSignUp'"
              class="codeWay"
              :rules="[
                { required: true, message: '请输入验证码' },
                { min: 4, max: 6, message: '请输入有效验证码' },
              ]"
              prop="telCode"
            >
              <el-input
                v-model="passFormData.telCode"
                placeholder="请输入验证码"
                size="large"
              />
              <el-button
                type="primary"
                class="codeBtn"
                :disabled="countDown != 0"
                @click="getCode(passFormRef)"
                >{{
                  countDown == 0 ? "获取验证码" : "验证码(" + countDown + "s)"
                }}</el-button
              >
            </el-form-item>
            <el-form-item
              v-if="flag === 'signUp'"
              :rules="[
                { required: true, message: '请输入密码' },
                { min: 8, max: 16, message: '密码在8到16位之间' },
                {
                  validator: (rule, value, callback) => {
                    if (!/\d/.test(value) || /^\d+$/.test(value)) {
                      callback('密码不能为纯数字或字母');
                    } else {
                      callback();
                    }
                  },
                },
              ]"
              prop="password"
              class="passwordInput"
            >
              <el-input
                type="password"
                show-password
                v-model="passFormData.password"
                placeholder="请输入密码"
                size="large"
                style="width: 304px"
              >
              </el-input>
            </el-form-item>
            <el-form-item
              v-if="flag === 'signUp'"
              :rules="[
                { required: true, message: '请输入确认密码' },
                { validator: validateLogInPassword },
              ]"
              prop="confirmPassword"
              class="passwordInput"
            >
              <el-input
                type="password"
                show-password
                v-model="passFormData.confirmPassword"
                placeholder="确认密码"
                size="large"
                style="width: 304px"
              />
            </el-form-item>
          </el-form>
          <el-button class="loginBtn" @click="loginBtn">登录</el-button>
        </div>
      </div>
    </div>
    <el-dialog
      v-model="sliderImgDialogVisable"
      align-center
      destroy-on-close="true"
      width="420"
      class="sliderImgDialog"
    >
      <verify :MG="MG" @loginImgVerify="loginImgVerify"></verify>
    </el-dialog>
  </el-dialog>
</template>
<script setup>
import { ref, inject, watchEffect, reactive, nextTick } from "vue";
import dialogLeftImg from "@/assets/images/header/dialogLeftImg.png";
import verify from "@/components/sliderImg/component/verify.vue";
import "@/components/sliderImg/sliderImg.js";
import "@/components/sliderImg/sliderImg.css";
import { ElMessage } from "element-plus";
import { useUserStore } from "@/store";
import { useRouter } from "vue-router";
const router = useRouter();
const userStore = useUserStore();
const MG = inject("MG");
const config = inject("config");
const dialogFormVisible = ref(false);
const sliderImgDialogVisable = ref(false);
const flag = ref("logIn"); // 登录或注册
const signUpWay = ref("authSignUp"); // 登录方式
const select = ref("中国+86");
const countDown = ref(0); // 倒计时时间
let timer = null; // 倒计时实例
const passFormRef = ref();
const passFormData = ref({
  telNumber: "",
  password: "",
  telCode: "",
  password: "",
  confirmPassword: "",
});
const closeDialog = () => {
  countDown.value = 0;
  clearInterval(timer);
  if (passFormRef.value) {
    passFormRef.value.resetFields();
  }
  dialogFormVisible.value = false;
};
// 弹窗打开事件
const openDialog = () => {};
const loginImgVerify = (code) => {
  sliderImgDialogVisable.value = false;
  MG.identity
    .getPhoneCode({
      phoneNumber: passFormData.value.telNumber,
      imageCaptcha: code,
      appRefCode: config.appRefCode,
    })
    .then((res) => {
      if (res == "验证码发送成功") {
        getSecond(60);
        ElMessage.success(res);
      } else {
        ElMessage.error(res);
      }
    });
};
watchEffect(() => {
  if (dialogFormVisible.value) {
  }
});
//登录
const loginBtn = () => {
  let query = {
    phoneNumber: passFormData.value.telNumber,
    phoneCaptcha: passFormData.value.telCode,
    appRefCode: config.appRefCode,
    platform: "string",
  };
  MG.identity.loginByMobilePhone(query).then((res) => {
    console.log("res", res);
    userStore.setToken(res.data.accessToken);
    getUserInfo();
  });
};
const getUserInfo = () => {
  MG.identity.getCurrentAppUser().then((res) => {
    console.log("res", res);
    if (res) {
      let userInfo = res.infoList.find((item) => item.type == "userInfo");
      let userTypeObj = res.infoList.find((item) => item.type == "userType");
      const userData = {
        userName: userInfo && userInfo.data ? JSON.parse(userInfo.data).name : "",
        school: userInfo && userInfo.data ? JSON.parse(userInfo.data).school : "",
        city: userInfo && userInfo.data ? JSON.parse(userInfo.data).city : "",
        cityCode: userInfo && userInfo.data ? JSON.parse(userInfo.data).cityCode : "",
        address: userInfo && userInfo.data ? JSON.parse(userInfo.data).address : "",
        userType:
          userTypeObj && userTypeObj.data ? JSON.parse(userTypeObj.data).userType : "",
      };
      localStorage.setItem("xiehe-isUserInfo", userData?.userType == "" ? "-1" : "1");
      let teacherRole = res.roleLinks.find((item) => item.role.refCode == "teacher");
      let teacherInfos = res.infoList.find((item) => item.type == "teacherInfo");
      let wechatInfo = res.infoList.find((item) => item.type == "WeChat");
      let studentInfo = res.infoList.find((item) => item.type == "Default");
      let phoneInfo = res.secretList.find((item) => item.type == "MobilePhone");
      // let nameAndPassword = res.secretList.find((item) => item.type == 'LoginNameAndPassword')
      let emailInfo = res.secretList.find((item) => item.type == "EMail");
      if (teacherRole && teacherInfos) {
        userStore.setUserInfo({
          ...userData,
          ...teacherInfos,
          phoneNumber: phoneInfo?.credential,
          Email: emailInfo ? emailInfo.credential : JSON.parse(teacherInfos.data).email,
          icon: wechatInfo?.icon,
          role: "Teacher",
          roleId: teacherRole.role.id,
          userId: res.userId,
        });
      } else if (wechatInfo) {
        userStore.setUserInfo({
          ...userData,
          ...wechatInfo,
          phoneNumber: phoneInfo?.credential,
          Email: emailInfo?.credential,
          role: "Student",
          userId: res.userId,
        });
      } else if (studentInfo) {
        userStore.setUserInfo({
          ...userData,
          ...studentInfo,
          icon: wechatInfo?.icon,
          phoneNumber: phoneInfo?.credential,
          Email: emailInfo?.credential,
          role: "Student",
          userId: res.userId,
        });
      } else if (phoneInfo) {
        userStore.setUserInfo({
          ...userData,
          ...phoneInfo,
          name: phoneInfo?.credential,
          icon: phoneInfo?.icon,
          phoneNumber: phoneInfo?.credential,
          role: "Student",
          userId: res.userId,
        });
      }
    }
    router.go(0);
  });
};
// 倒计时
const getSecond = (time) => {
  if (!timer) {
    countDown.value = time;
    timer = setInterval(() => {
      countDown.value--;
      if (countDown.value == 0) {
        clearInterval(timer);
        timer = null;
      }
    }, 1000);
  }
};
// 登录和重置密码按钮按钮
const signInSystem = async (formEl) => {
  if (!formEl) return;
  formEl.validate((valid) => {
    if (valid) {
      // if (signUpWay.value === 'phone') {
      //   // 账号密码登录
      //   passwordSignUp()
      // } else if (signUpWay.value == 'authSignUp') {
      //   // 验证码登录
      //   codeSignUp()
      // } else {
      //   // 重置密码
      //   changePassword()
      // }
    }
  });
};
const logIn = () => {
  dialogFormVisible.value = true;
  flag.value = "logIn";
};
// 打开注册弹窗
const signUp = () => {
  dialogFormVisible.value = true;
  flag.value = "signUp";
};
const wechatLoginOpen = () => {
  signUpWay.value = "wechat";
};
defineExpose({
  logIn,
  signUp,
});
</script>
<style lang="less" scoped>
// 用户信息填写界面
.changeUser {
  .prompt-title {
    width: 80%;
    line-height: 24px;
    color: #000;
    span {
      display: inline-block;
    }
  }
}
.fansdialog {
  width: 806px;
  .leftImg {
    box-sizing: border-box;
    width: 403px;
  }
  .el-dialog__header {
    padding: 0;
  }
  .el-dialog__body {
    width: 806px;
    height: 575px;
    display: flex;
    padding: 0 !important;
  }
  .leftImg {
    .el-image__inner {
      width: 403px;
    }
  }
  .el-dialog__header {
    padding: 0;
  }
  .el-dialog__body {
    width: 806px;
    display: flex;
    padding: 0 !important;
  }
}
.agreementDialog {
  width: 760px;
  height: 600px;
  p span {
    line-height: 24px;
  }
  .el-dialog__header {
    font-size: 18px;
    color: #333;
  }
  .el-dialog__body {
    overflow: auto;
    height: 500px;
    width: 760px;
  }
  .el-dialog__footer {
    display: flex;
    justify-content: center;
  }
}
.wechatTipsDialog {
  .el-dialog__header {
    font-size: 18px;
  }
  .el-dialog__body {
    display: flex;
    align-items: center;
    p {
      margin-left: 10px;
      line-height: 24px;
    }
  }
}
.sliderImgDialog {
  .el-dialog__body {
    min-height: 320px;
  }
}
</style>
<style lang="less">
/** 登录注册弹窗 */
.logIn {
  width: 403px;
  height: 100%;
  padding-top: 48px;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  .signUpTitle {
    width: 100%;
    ul {
      display: flex;
      justify-content: center;
      width: 100%;
      li {
        height: 20px;
        display: flex;
        align-items: center;
        .el-image {
          margin-right: 5px;
          width: 20px;
        }
      }
      li:nth-child(2n + 1) {
        cursor: pointer;
        margin: 0 10px;
      }
      li:first-child {
        margin-left: 0;
        .el-image {
          width: 10px;
        }
      }
    }
  }
  /** 微信登录 */
  .signUpContent {
    display: flex;
    height: 400px;
    flex-wrap: wrap;
    flex-direction: column;
    justify-content: space-around;
    align-content: center;
    .el-image {
      width: 176px;
    }
    h2 {
      font-size: 20px;
      color: #000;
      font-weight: 700;
      text-align: center;
    }
    p {
      text-align: center;
      line-height: 26px;
    }
    .wechatCode {
      h2 {
        margin-bottom: 24px;
      }
    }
  }
  /** 密码登录 */
  .singUpPhone {
    height: 400px;
    display: flex;
    flex-direction: column;
    align-items: center;
    h2 {
      padding-top: 35px;
      font-size: 20px;
      color: #000;
      font-weight: 700;
      text-align: center;
    }
    .back {
      display: flex;
      align-items: center;
      cursor: pointer;
      margin: 10px 0px 0px 20px;
      align-self: flex-start;
      font-size: 12px;
      color: #333;
    }
    .el-form {
      margin-top: 26px;
    }
    .signInBtn {
      width: 304px;
      height: 41px;
      margin-bottom: 33px;
      border-radius: 3px;
      // opacity: 0.55;
      color: #fff;
      font-size: 14px;
    }
    .codeBtn {
      width: 101px;
      height: 41px;
      background-color: #019e58;
      // opacity: 0.55;
    }
    .yanzhengBtn {
      width: 100%;
      height: 41px;
      background-color: #019e58;
      color: #fff;
    }
    .loginBtn {
      width: 76%;
      height: 41px;
      background: linear-gradient(90deg, #019e58 0%, #144941 100%);
      color: #fff;
      margin-top: 50px;
    }
    .el-image {
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    .authSignUp {
      width: 305px;
      flex: 1;
      display: flex;
      justify-content: end;
      align-items: end;
      padding-bottom: 20px;
      span {
        cursor: pointer;
        color: #333;
        font-size: 12px;
      }
    }
    .codeWay {
      .el-input {
        width: 195px;
      }
      .el-button {
        width: 100px;
        padding: 0;
        margin: 0 0 0 10px;
      }
      .authCodeBox {
        width: 100px;
        height: 50px;
        margin-left: 10px;
        cursor: pointer;
        position: relative;
        span {
          position: absolute;
          top: 35px;
          height: 10px;
          margin-bottom: 20px;
          font-size: 10px;
          color: #1f971f;
        }
      }
    }
  }
  .claus {
    margin-bottom: 10px;
    color: #000;
    font-size: 12px;
    width: 100%;
    text-align: center;
    line-height: 26px;
  }
}
.policy {
  cursor: pointer;
  color: #ff6c00;
}
/** 注册表单 */
.signUp {
  width: 403px;
  justify-content: space-around;
  color: #333;
  font-size: 12px;
  span:first-child,
  span:last-child {
    cursor: pointer;
  }
  .logInTitle {
    width: 96%;
    font-size: 16px;
    margin: 20px 0 0 20px;
    font-weight: bold;
  }
  h4 {
    font-size: 16px;
    color: #ff6c00;
  }
  .logInBox {
    margin-top: 20px;
    padding: 0 40px;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    .el-form-item {
      .el-button {
        width: 100px;
        height: 41px;
        border-radius: 3px;
        color: #fff;
        font-size: 14px;
      }
    }
    .agreement {
      height: 40px;
      display: flex;
      align-items: center;
      margin: 30px 0 0 0;
      line-height: 32px;
      height: 32px;
      font-size: 12px;
      color: #000;
      .el-checkbox {
        margin-right: 10px;
      }
      .el-link {
        font-size: 12px;
      }
      p {
        height: 100%;
        display: flex;
        align-items: center;
      }
    }
    .hint {
      font-size: 11px;
      color: #545c63;
    }
    .codeWay {
      .el-input {
        width: 195px;
      }
      .el-button {
        width: 100px;
        padding: 0;
        margin: 0 0 0 10px;
      }
      .authCodeBox {
        width: 100px;
        height: 50px;
        margin-left: 10px;
        cursor: pointer;
        position: relative;
        span {
          position: absolute;
          top: 35px;
          left: 0;
          width: 100px;
          font-size: 10px;
          color: #1f971f;
        }
      }
    }
  }
  .logInBtn {
    width: 304px;
    height: 41px;
    margin-top: 10px;
    margin-bottom: 20px;
    border-radius: 3px;
    color: #fff;
    font-size: 14px;
  }
  /** 选择用户类型 */
  .changeUser {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    .el-form-item {
      &:last-child {
        margin-bottom: 0;
      }
      .el-button {
        height: 40px;
        margin-left: 10px;
      }
    }
    h2 {
      font-size: 20px;
      margin-top: 70px;
      color: #000;
      font-weight: bold;
    }
    .el-radio-group {
      display: flex;
      flex-direction: column;
      .el-radio-button {
        width: 166px;
      }
      /deep/ .el-radio-button__inner {
        width: 166px;
        height: 41px;
        line-height: 24px;
        border-radius: 4px;
        border: 0;
        border: 1px solid #dcdfe6;
      }
      .el-radio-button:nth-child(n + 1) {
        margin-bottom: 27px;
      }
    }
  }
}
.selectPhone {
  background: #fff;
}
// .el-select {
//   width: 100px;
//   height: 30px;
//   color: red;
//   border: none !important;
//   /deep/ .select-trigger {
//     height: 100%;
//     .el-input--suffix {
//       height: 100%;
//       background-color: #fff;
//     }
//   }
// }
</style>
src/plugin/axios/index.ts
@@ -1,69 +1,84 @@
import axios from "axios";
import myConfig from "@/assets/js/config.js";
import toolClass from "@/assets/js/toolClass.js";
import router from "@/router";
import axios from 'axios'
import myConfig from '@/assets/js/config.js'
import toolClass from '@/assets/js/toolClass.js'
import router from '@/router'
// 创建 axios 实例
const service = axios.create({
  baseURL: myConfig.requestCtx,
  timeout: myConfig.requestTimeOut, // 请求超时时间
});
})
// 请求拦截器
service.interceptors.request.use(
  (config) => {
    let token = localStorage.getItem(myConfig.tokenKey);
    if (token) config.headers["Authorization"] = `bearer ${token}`;
    return config;
    let token = localStorage.getItem(myConfig.tokenKey)
    console.log(token, 'token')
    if (token) config.headers['Authorization'] = `bearer ${token}`
    return config
  },
  (error) => {
    // 发送失败
    Promise.reject(error);
  }
);
    Promise.reject(error)
  },
)
// 响应拦截器
service.interceptors.response.use(
  (response) => {
    // dataAxios 是 axios 返回数据中的 data
    const dataAxios = response.data;
    if (typeof dataAxios.data === "boolean") {
      return dataAxios.data;
    const dataAxios = response.data
    if (typeof dataAxios.data === 'boolean') {
      return dataAxios.data
    }
    if (response.config.responseType == "blob") {
      return dataAxios;
    if (response.config.responseType == 'blob') {
      return dataAxios
    }
    const { success } = dataAxios;
    const { success } = dataAxios
    if (dataAxios.currentDate) {
      sessionStorage.currentDate = new Date(dataAxios.currentDate).getTime();
      sessionStorage.currentDate = new Date(dataAxios.currentDate).getTime()
    }
    // 根据 code 进行判断
    if (response.status == 200 && response.statusText == "OK") {
      return dataAxios.data ? dataAxios.data : dataAxios;
    if (success) {
      return dataAxios.data ? dataAxios.data : dataAxios
    } else {
      // 提示错误
    }
  },
  (error) => {
    if (
      (error.response && error.response.status == 401) ||
      error.code == "ERR_NETWORK"
    ) {
      console.log(router, "router");
    if ((error.response && error.response.status == 401) || error.code == 'ERR_NETWORK') {
      console.log(router, 'router')
      localStorage.removeItem(myConfig.tokenKey);
      localStorage.removeItem("jesk-userInfo");
      router.push({
        name: "login",
      });
      localStorage.removeItem(myConfig.tokenKey)
      localStorage.removeItem('xiehe-userInfo')
      localStorage.removeItem('xiehe-isUserInfo')
      localStorage.removeItem('alreadyElectronicBook')
      localStorage.removeItem('alreadyPaperBook')
      localStorage.removeItem('electronicBookList')
      localStorage.removeItem('paperBookList')
      sessionStorage.removeItem('cartNumber')
      const url = window.location.hash.slice(1)
      console.log(url, 'url')
      if (url.includes('showLogin=1')) {
        router.push(url)
      } else {
        // router.push(url)
        if (url.includes('?')) {
          console.log(url.includes('?'))
          router.push(url)
        } else {
          router.push(url + '?showLogin=1')
        }
      }
    } else {
      if (error.response && error.response.data && error.response.data.error) {
        console.error(error.response.data.error.msg);
        console.error(error.response.data.error.msg)
      } else {
        console.error("请求发生错误");
        console.error('请求发生错误')
      }
    }
    return Promise.reject(error);
  }
);
    return Promise.reject(error)
  },
)
export default service;
export default service
src/router/index.js
@@ -1,5 +1,8 @@
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
import HomeView from '../views/home/index.vue'
import aboutUs from '../views/aboutUs/index.vue'
import bookStore from '../views/bookStore/index.vue'
import bookdetail from '../views/bookStore/detail.vue'
import PageLayout from '../layout/baseLayout.vue'
const router = createRouter({
  history: createWebHashHistory(import.meta.env.BASE_URL),
@@ -15,6 +18,21 @@
          name: 'home',
          component: HomeView,
        },
        {
          path: '/aboutUs',
          name: 'aboutUs',
          component: aboutUs,
        },
        {
          path: '/bookdetail',
          name: 'bookdetail',
          component: bookdetail,
        },
        {
          path: '/bookStore',
          name: 'bookStore',
          component: bookStore,
        },
        //个人中心
        {
          path: '/personalCenter',
src/store/index.js
New file
@@ -0,0 +1,9 @@
import { createPinia } from 'pinia'
// 创建pinia实例
const pinia = createPinia()
export default pinia
// export * from './modules/breadcrumb'
export * from './modules/user'
src/store/index.ts
File was deleted
src/store/modules/breadcrumb.ts
File was deleted
src/store/modules/user.js
File was renamed from src/store/modules/user.ts
@@ -1,54 +1,46 @@
// 用户信息
import { defineStore } from 'pinia'
import config from '@/assets/js/config'
import config from '@/assets/js/config.js'
import { ref } from 'vue'
interface userInfo {
  userName: string
  userType: string
  roleId?: any
  role?: any
  userId?: number
  name?: string
}
const { tokenKey, userInfoKey } = config
export const useUserStore = defineStore('user', () => {
  const token = localStorage.getItem(config.tokenKey)
    ? ref<string>(localStorage.getItem(config.tokenKey) as string)
    : ref<string>()
  const userInfo = localStorage.getItem(config.userInfoKey)
    ? ref<userInfo>(JSON.parse(localStorage.getItem(config.userInfoKey) as string))
    : ref<userInfo>()
  const setToken = (value: string) => {
  const token = localStorage.getItem(tokenKey) ? ref(localStorage.getItem(tokenKey)) : ref()
  const userInfo = localStorage.getItem(userInfoKey)
    ? ref(JSON.parse(localStorage.getItem(userInfoKey)))
    : ref()
  const setToken = (value) => {
    token.value = value
    localStorage.setItem(config.tokenKey, value)
    localStorage.setItem(tokenKey, value)
  }
  const setUserInfo = (value: userInfo) => {
  const setUserInfo = (value) => {
    userInfo.value = value
    localStorage.setItem(config.userInfoKey, JSON.stringify(value))
    localStorage.setItem(userInfoKey, JSON.stringify(value))
  }
  // 退出登录
  const delteUserInfo = () => {
    ;((token.vlaue = ''), (userInfo.value = { userName: '', userType: '' }))
    localStorage.removeItem(config.tokenKey)
    localStorage.removeItem(config.userInfoKey)
    localStorage.removeItem(tokenKey)
    localStorage.removeItem(userInfoKey)
    localStorage.removeItem('xiehe-isUserInfo')
  }
  // 购物车数量
  let cartNum = ref<number>(1)
  let cartNum = ref(1)
  // 更新右侧弹出框购物车的数量
  const updateRightPop = () => {
    cartNum.value += 1
  }
  // 购物车商品id
  const shoppingIds = ref<number[]>([])
  const updateShoppingIds = (ids: number[]) => {
  const shoppingIds = ref([])
  const updateShoppingIds = (ids) => {
    shoppingIds.value = ids
  }
  // 已购买的商品id
  const buyIds = ref<number[]>([])
  const updateBuyIds = (ids: number[]) => {
  const buyIds = ref([])
  const updateBuyIds = (ids) => {
    buyIds.value = ids
  }
@@ -83,29 +75,29 @@
    ? ref(JSON.parse(localStorage.getItem('alreadyElectronicBook')))
    : ref([])
  // 添加电子样书列表
  const appplyElectronicBook = (value: data) => {
  const appplyElectronicBook = (value) => {
    electronicBookList.value.push(value)
    localStorage.setItem('electronicBookList', JSON.stringify(electronicBookList.value))
  }
  //添加纸质样式列表
  const appplyPaperBook = (value: data) => {
  const appplyPaperBook = (value) => {
    paperBookList.value.push(value)
    localStorage.setItem('paperBookList', JSON.stringify(paperBookList.value))
  }
  //删除电子样书列表
  const removeElectronicBook = (value: int) => {
  const removeElectronicBook = (value) => {
    electronicBookList.value.splice(value, 1)
    localStorage.setItem('electronicBookList', JSON.stringify(electronicBookList.value))
  }
  //删除纸质样式
  const removePaperBook = (value: int) => {
  const removePaperBook = (value) => {
    paperBookList.value.splice(value, 1)
    localStorage.setItem('paperBookList', JSON.stringify(paperBookList.value))
  }
  const emptyBookList = (value: data) => {
  const emptyBookList = (value) => {
    if (value && value.type == 'eBook') {
      electronicBookList.value = []
      localStorage.setItem('electronicBookList', JSON.stringify(electronicBookList.value))
@@ -123,12 +115,12 @@
  }
  //已申请图书
  const alreadyPaperBookList = (value: data) => {
  const alreadyPaperBookList = (value) => {
    alreadyPaperBook.value = value.list
    localStorage.setItem('alreadyPaperBook', JSON.stringify(alreadyPaperBook.value))
  }
  const alreadyElectronicBookList = (value: data) => {
  const alreadyElectronicBookList = (value) => {
    alreadyElectronicBook.value = value.list
    localStorage.setItem('alreadyElectronicBook', JSON.stringify(alreadyElectronicBook.value))
  }
@@ -144,6 +136,7 @@
    removePaperBook,
    emptyBookList,
    alreadyPaperBookList,
    alreadyElectronicBookList,
    alreadyElectronicBookList
  }
})
src/views/aboutUs/index.vue
New file
@@ -0,0 +1,378 @@
<template>
  <div class="homePage">
    <el-carousel :height="screenheight + 'px'">
      <el-carousel-item v-for="(item, index) in banner" :key="index">
        <div class="bannerBox imgBox">
          <img id="autoHeight" class="bannerImg" :src="item.icon" @click="bannerLink(item)" />
        </div>
      </el-carousel-item>
    </el-carousel>
    <div class="contentBox">
      <div class="crumbs">
        <el-breadcrumb separator-class="el-icon-arrow-right">
          <el-breadcrumb-item :to="{ name: 'home' }">首页</el-breadcrumb-item>
          <el-breadcrumb-item>关于我们</el-breadcrumb-item>
        </el-breadcrumb>
      </div>
      <div class="aboutUs">
        <div class="aboutTitle">
          <div class="titleBox1">
            <img class="autoImg" src="@/assets/images/xiehe/about/yinhao.png" alt="" />
          </div>
          <div class="titleText">Publisher Introduction</div>
        </div>
        <div class="textBox" v-html="publisherIntroduction"></div>
        <div class="statisticsBox">
          <div class="statisticsItem">
            <div class="statisticsNum">
              {{ publisherData.focusOnMedical }} <span class="circleBox">年</span>
            </div>
            <div class="statisticsTitle">专注医学出版</div>
          </div>
          <div class="statisticsItem">
            <div class="statisticsNum">{{ publisherData.topExpertDatabase }}+ 位</div>
            <div class="statisticsTitle">顶级专家库</div>
          </div>
          <div class="statisticsItem">
            <div class="statisticsNum">
              {{ publisherData.accumulatedTextbooks }}+ <span class="circleBox">本</span>
            </div>
            <div class="statisticsTitle">累计出版教材教辅</div>
          </div>
          <div class="statisticsItem">
            <div class="statisticsNum">
              {{ publisherData.academicJournals }} <span class="circleBox">本</span>
            </div>
            <div class="statisticsTitle">学术期刊</div>
          </div>
          <div class="statisticsItem">
            <div class="statisticsNum">
              {{ publisherData.dualCoreJournal }} <span class="circleBox">本</span>
            </div>
            <div class="statisticsTitle">双核心期刊</div>
          </div>
        </div>
      </div>
    </div>
    <div class="brandCultureBox">
      <div class="brandCultureTop">
        <div class="CultureBox">
          <div class="brandCultureTitle">
            <div>理念与品牌文化</div>
            <div class="enText">Philosophy & Brand Culture</div>
          </div>
          <div class="cultureList" v-loading="loading">
            <div class="cultureItem firstItem">
              <div class="cultureTitle" style="border-bottom: 1px solid rgba(255, 255, 255, 0.1)">
                <div class="leftIcon">
                  <img class="autoImg" src="@/assets/images/xiehe/about/zongzhi.png" alt="" />
                </div>
                <div class="titleTextInfo">
                  <div class="itemTitle" style="color: #fff">{{ ideaBrandCulture[0]?.name }}</div>
                  <div class="itemSubTitle" style="color: #fff">
                    {{ ideaBrandCulture[0]?.EnglishName }}
                  </div>
                </div>
              </div>
              <div
                class="itemText"
                style="color: #d5d5d5"
                v-html="ideaBrandCulture[0]?.content"
              ></div>
            </div>
            <div class="cultureItem">
              <div class="cultureTitle">
                <div class="leftIcon">
                  <img class="autoImg" src="@/assets/images/xiehe/about/beijing.png" alt="" />
                </div>
                <div class="titleTextInfo">
                  <div class="itemTitle">{{ ideaBrandCulture[1]?.name }}</div>
                  <div class="itemSubTitle">
                    {{ ideaBrandCulture[1]?.EnglishName }}
                  </div>
                </div>
              </div>
              <div class="itemText" v-html="ideaBrandCulture[1]?.content"></div>
            </div>
            <div class="cultureItem">
              <div class="cultureTitle">
                <div class="leftIcon">
                  <img class="autoImg" src="@/assets/images/xiehe/about/zizhi.png" alt="" />
                </div>
                <div class="titleTextInfo">
                  <div class="itemTitle">{{ ideaBrandCulture[2]?.name }}</div>
                  <div class="itemSubTitle">
                    {{ ideaBrandCulture[2]?.EnglishName }}
                  </div>
                </div>
              </div>
              <div class="itemText" v-html="ideaBrandCulture[2]?.content"></div>
            </div>
            <div class="cultureItem">
              <div class="cultureTitle">
                <div class="leftIcon">
                  <img class="autoImg" src="@/assets/images/xiehe/about/fazhan.png" alt="" />
                </div>
                <div class="titleTextInfo">
                  <div class="itemTitle">{{ ideaBrandCulture[3]?.name }}</div>
                  <div class="itemSubTitle">
                    {{ ideaBrandCulture[3]?.EnglishName }}
                  </div>
                </div>
              </div>
              <div class="itemText" v-html="ideaBrandCulture[3]?.content"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="page-container">
      <MapContainer />
    </div>
  </div>
</template>
<script setup>
import moment from 'moment'
import MapContainer from '@/components/MapContainer.vue'
import { ref, onBeforeMount, inject, reactive, onMounted } from 'vue'
let screenheight = ref(document.documentElement.clientHeight / 2)
const MG = inject('MG')
const config = inject('config')
const tool = inject('tool')
const banner = reactive([])
let publisherIntroduction = ref('')
let publisherData = ref('')
let ideaBrandCulture = ref([])
let loading = ref(false)
const getBanner = () => {
  MG.resource
    .getItem({
      path: 'banner\\homeBanner',
      fields: { link: [] },
      paging: { start: 0, size: 9 },
    })
    .then((res) => {
      banner.push(...res.datas)
      console.log(res.datas)
    })
}
const getPublisherIntroduction = () => {
  MG.resource
    .getItem({
      path: 'aboutUs\\publisherIntroduction',
      fields: { content: [] },
      paging: { start: 0, size: 9 },
    })
    .then((res) => {
      console.log(res.datas)
      publisherIntroduction.value = res.datas[0].content
    })
}
const getIdeaBrandCulture = () => {
  loading.value = true
  MG.resource
    .getItem({
      path: 'aboutUs\\ideaBrandCulture',
      fields: { content: [], EnglishName: [] },
      paging: { start: 0, size: 9 },
    })
    .then((res) => {
      console.log(res.datas, 'ideaBrandCulture')
      ideaBrandCulture.value = res.datas
      loading.value = false
    })
}
const getPublisherData = () => {
  MG.resource
    .getItem({
      path: 'aboutUs\\publisherData',
      fields: {
        academicJournals: [],
        accumulatedTextbooks: [],
        dualCoreJournal: [],
        focusOnMedical: [],
        topExpertDatabase: [],
      },
      paging: { start: 0, size: 1 },
    })
    .then((res) => {
      console.log(res.datas, 'publisherData')
      publisherData.value = res.datas[0]
    })
}
onMounted(() => {
  getBanner()
  getPublisherIntroduction()
  getPublisherData()
  getIdeaBrandCulture()
})
</script>
<style lang="less" scoped>
.homePage {
  min-width: 1220px;
  min-height: calc(100vh - 61.8%);
  background-color: #fff;
}
.contentBox {
  background-color: #fff;
  padding-bottom: 100px;
  margin-top: 35px;
  .aboutUs {
    width: 100%;
    font-size: 16px;
    border-top: 1px solid #ededed;
    margin-top: 40px;
    .aboutTitle {
      display: flex;
      width: 100%;
      padding-top: 30px;
      .titleBox1 {
        position: relative;
        width: 50px;
        height: 50px;
        margin-right: 20px;
      }
      .titleText {
        font-size: 48px;
        font-weight: 700;
        opacity: 0.05;
      }
    }
    .block {
      display: inline-block;
      width: 4px;
      height: 4px;
      margin-right: 10px;
      vertical-align: middle;
      background: #dadada;
    }
    .selected {
      background-color: #e7f9ef;
      .block {
        background-color: #008e3f;
      }
    }
    .title {
      padding: 0;
      font-weight: 700;
      text-align: center;
      background: #008e3f;
      color: #fff;
      line-height: 36px;
      border-bottom: 0;
    }
    div {
      cursor: pointer;
      // border-bottom: 1px dashed #ededed;
    }
    .colorText {
      color: #144941;
    }
    .textBox {
      line-height: 20px;
      margin-top: 30px;
      p {
        margin-top: 30px;
      }
    }
  }
  .statisticsBox {
    display: flex;
    justify-content: space-between;
    margin-top: 80px;
    text-align: center;
    .statisticsNum {
      font-size: 48px;
    }
    .statisticsTitle {
      margin-top: 10px;
    }
    .circleBox {
      width: 26px;
      height: 26px;
      display: inline-block;
      font-size: 20px;
      line-height: 26px;
      color: #fff;
      background-color: #144941;
      border-radius: 50%;
    }
  }
}
.brandCultureTop {
  background-image: url(@/assets/images/xiehe/about/wenhua_bg.png);
  width: 100%;
  height: 500px;
  padding-top: 55px;
}
.brandCultureTitle {
  font-size: 36px;
  color: #fff;
  font-weight: 700;
  text-align: center;
}
.cultureList {
  display: flex;
  justify-content: space-between;
  width: 100%;
  margin-top: 60px;
}
.cultureItem {
  width: 320px;
  height: 320px;
  background-color: #fff;
  margin-left: 30px;
  padding: 20px;
  box-sizing: border-box;
}
.firstItem {
  background-color: #144941;
  color: #fff;
  width: 320px;
  height: 320px;
  text-align: center;
  margin-left: 0px;
}
.CultureBox {
  width: 1200px;
  margin: 0 auto;
}
.leftIcon {
  width: 58px;
  height: 58px;
  position: relative;
}
.cultureTitle {
  display: flex;
  border-bottom: 1px solid #dedede;
  padding-bottom: 16px;
}
.titleTextInfo {
  margin-left: 20px;
  text-align: left;
}
.itemTitle {
  font-size: 18px;
  font-weight: 700;
  line-height: 36px;
  color: #333;
}
.itemSubTitle {
  color: #000;
  opacity: 0.5;
}
.itemText {
  font-size: 16px;
  line-height: 28px;
  color: #000;
  padding-top: 20px;
}
</style>
src/views/bookStore/detail.vue
New file
@@ -0,0 +1,593 @@
<template>
  <div class="homePage">
    <div class="infoBox">
      <div class="contentBox">
        <div class="crumbs">
          <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item :to="{ name: 'bookStore' }">数字教材</el-breadcrumb-item>
            <el-breadcrumb-item>详情</el-breadcrumb-item>
          </el-breadcrumb>
        </div>
        <div class="infoTag" v-if="bookInfo.projectTitle">
          <el-tooltip
            class="item"
            effect="dark"
            :content="bookInfo.projectTitle"
            placement="top-start"
          >
            <div class="tagText">
              {{ bookInfo.projectTitle }}
            </div>
          </el-tooltip>
        </div>
        <div class="bookDetail">
          <div class="bookImg">
            <img class="autoImg" :src="bookInfo.icon" alt="" />
          </div>
          <span class="iconfont icon-tubiaozhizuo"></span>
          <div class="detailBox">
            <div class="bookTitle">
              <div class="bookName" :title="bookInfo.name">
                {{ bookInfo.name }}
              </div>
              <div class="bookTag" :title="bookInfo.seriesName">
                {{ bookInfo.seriesName }}
              </div>
              <div class="collectBox">
                <img
                  @click="collectBook"
                  v-if="bookInfo.isFavourite"
                  class="buyIcon"
                  src="@/assets/images/bookStore/shoucang.svg"
                  style="margin-right: 10px"
                />
                <span
                  @click="collectBook"
                  v-else
                  class="iconfont icon-shoucang"
                  style="margin-right: 10px"
                >
                </span>
                <div class="collectText" @click="collectBook" v-if="bookInfo.isFavourite">
                  已收藏
                </div>
                <div class="collectText" @click="collectBook" v-else>收藏</div>
              </div>
            </div>
            <div class="authorBox">
              <div class="titleBox1">
                <div>作者:</div>
                <div>出版时间:</div>
              </div>
              <div class="valueBox">
                <div>
                  {{ bookInfo.author ? bookInfo.author : '-' }}
                </div>
                <div>
                  {{
                    bookInfo.publicationDate
                      ? moment(bookInfo.publicationDate).format('YYYY-MM-DD')
                      : '-'
                  }}
                </div>
              </div>
              <div class="titleBox1" style="margin-left: 30px">
                <div>ISBN:</div>
                <div>版次:</div>
              </div>
              <div class="valueBox">
                <div>
                  {{ bookInfo.isbn ? bookInfo.isbn : '-' }}
                </div>
                <div>
                  {{ bookInfo.pubNumber ? bookInfo.pubNumber : '-' }}
                </div>
              </div>
            </div>
            <div class="authorBox" style="box-sizing: border-box">
              <div class="titleBox1">
                <div>一级分类:</div>
                <div>二级分类:</div>
              </div>
              <div class="valueBox">
                <div>全国高等职业教育预防医学专业规划教材</div>
                <div>高等职业教育</div>
              </div>
            </div>
            <div class="purchaseBox">
              <div class="priceBox">
                <span v-if="bookInfo.price && bookInfo.price > 0">
                  <span>定价:</span><span>¥</span> <span>{{ bookInfo.price || '-' }}</span
                  ><span v-if="bookInfo.VirtualPrice">原价:¥{{ bookInfo.VirtualPrice }}</span>
                </span>
                <span class="price" v-else>
                  <span class="freePrice">免费</span>
                </span>
              </div>
              <div
                class="buyInfo"
                v-if="
                  (currentRoute !== 'teachingServices' && bookInfo.paperBookDD) ||
                  bookInfo.paperBookJD ||
                  bookInfo.paperBookTmall
                "
              >
                纸质书其他购买渠道:
                <span @click="toJDLink" v-if="bookInfo.paperBookJD">
                  <img class="buyIcon" src="@/assets/images/bookStore/京东icon-01.svg" />京东</span
                >
                <span @click="toDDLink" v-if="bookInfo.paperBookDD"
                  ><img class="buyIcon" src="@/assets/images/bookStore/当当网.svg" />当当</span
                >
                <span @click="toTmLink" v-if="bookInfo.paperBookTmall"
                  ><img
                    class="buyIcon"
                    src="@/assets/images/bookStore/tianmaologo2.svg"
                  />天猫</span
                >
              </div>
            </div>
            <div class="btnBox">
              <el-button
                v-if="
                  currentRoute !== 'teachingServices' &&
                  !bookInfo.alreadyBuy &&
                  bookInfo.isSell &&
                  bookInfo.isSell == '1'
                "
                type="primary"
                :disabled="bookInfo.alreadyBuy"
                @click="gotoOrder"
                >电子书购买</el-button
              >
              <el-button
                v-if="bookInfo.pdfFreeFile && !bookInfo.alreadyBuy"
                type="primary"
                plain
                style="min-width: 98px"
                @click="previewBook"
                >试读</el-button
              >
              <el-button
                v-else-if="bookInfo.pdfFile && bookInfo.alreadyBuy"
                type="primary"
                plain
                style="min-width: 98px"
                @click="previewBook"
                >立即阅读</el-button
              >
              <el-button
                v-if="currentRoute == 'teachingServices' && !bookInfo.alreadyBuy"
                plain
                @click="addEbook"
                >电子样书</el-button
              >
              <el-button v-if="currentRoute == 'teachingServices'" plain @click="addPaperBook"
                >纸质样书</el-button
              >
            </div>
          </div>
        </div>
        <el-dialog title="联系编辑" :visible.sync="contactVisible" width="30%" :lock-scroll="false">
          <div class="contactBox" v-if="bookInfo.editor">
            <div class="contacItem">
              <i class="iconfont icon-renwu-ren contacIcon"></i>
              {{ bookInfo.editor.name }}
            </div>
            <div class="contacItem">
              <i class="iconfont icon-QQ contacIcon"></i>
              {{ bookInfo.editor.qq }}
            </div>
            <div class="contacItem">
              <i class="iconfont icon-tongxunlu contacIcon"></i>
              {{ bookInfo.editor.phone }}
            </div>
            <div class="contacItem">
              <i class="iconfont icon-dianhua contacIcon"></i>
              {{ bookInfo.editor.telephone }}
            </div>
          </div>
          <el-empty v-else description="暂无数据" class="empty" :image-size="100"></el-empty>
        </el-dialog>
        <el-dialog title="信息反馈" :visible.sync="dialogVisible" width="50%" :lock-scroll="false">
          <div class="infoDialog">
            <el-input
              type="textarea"
              :rows="8"
              placeholder="详细描述您所遇到的问题,有助于快速给您反馈!"
              v-model="textarea"
            >
            </el-input>
            <div class="subBtn">
              <el-button type="primary" @click="sendDiscuss">提交</el-button>
            </div>
            <div class="infoList">
              <div class="infoItem" v-for="(item, index) in commentList" :key="index">
                <div class="infoImg">
                  <img v-if="item.icon" class="autoImg" :src="item.icon" alt="" />
                  <i v-else class="el-icon-user-solid"></i>
                </div>
                <div class="infoContent">
                  <div class="infoTitle">
                    <div class="userNameBox">{{ item.content.name }}</div>
                    <div class="userNameBox">
                      {{ moment(item.createDate).format('YYYY-MM-DD') }}
                    </div>
                  </div>
                  <div class="infoText">
                    {{ item.content.content }}
                  </div>
                </div>
              </div>
            </div>
          </div>
        </el-dialog>
      </div>
    </div>
    <div class="detailContent contentBox">
      <div class="resourceBox">
        <div class="tabsBox">
          <el-tabs v-model="editableTabsValue" type="card" class="demo-tabs">
            <el-tab-pane
              v-for="item in editableTabs"
              :key="item.name"
              :label="item.title"
              :name="item.name"
            >
              {{ item.content }}
            </el-tab-pane>
          </el-tabs>
        </div>
        <div v-if="editableTabsValue == '1'" class="textbookInfo">
          <div class="textbookInfoItem">
            <div class="titleBorderBox">图书简介</div>
            <div class="textbookContent"></div>
          </div>
          <div class="textbookInfoItem">
            <div class="titleBorderBox">作者简介</div>
            <div class="authorInfo"></div>
          </div>
        </div>
        <div v-else-if="editableTabsValue == '2'" class="catalogue">bbbb</div>
      </div>
      <div class="recommendBox"></div>
    </div>
  </div>
</template>
<script setup>
import moment from 'moment'
import { ref, onBeforeMount, inject, reactive, onMounted } from 'vue'
const MG = inject('MG')
import { useRouter, useRoute } from 'vue-router'
const route = useRoute()
const router = useRouter()
let bookInfo = ref({})
let digitalTextId = ref('')
let editableTabsValue = ref('1')
const editableTabs = reactive([
  {
    title: '教材信息',
    name: '1',
  },
  {
    title: '目录',
    name: '2',
  },
  {
    title: '配套资源',
    name: '3',
  },
  {
    title: '题库',
    name: '4',
  },
  {
    title: '教师资源',
    name: '5',
  },
  {
    title: '资源统计',
    name: '6',
  },
])
onMounted(() => {
  digitalTextId.value = route.query.bookId
  getBookDetail(digitalTextId.value)
})
const getBookDetail = (id) => {
  const query = {
    path: '*',
    queryType: '*',
    productId: id,
    storeInfo: 'defaultGoodsStore1',
    coverSize: {
      height: 300,
      width: 210,
    },
    fields: {
      author: [],
      isbn: [],
      editionPrinting: [],
      publicationDate: [],
      content: [],
      authorIntroduction: [],
      catalogue: [],
      probationPage: [],
      teachingLevel: [],
      professionalCategory: [],
      executiveEditor: [],
    },
  }
  MG.store.getProductDetail(query).then((res) => {
    console.log(res, 'res')
    bookInfo.value = res.datas
    console.log(res.datas, 'res')
  })
}
</script>
<style lang="less" scoped>
.homePage {
  min-width: 1220px;
  min-height: calc(100vh - 61.8%);
  background-color: #fff;
  padding-bottom: 100px;
}
.infoBox {
  width: 100%;
  height: 530px;
  padding-top: 10px;
  background-color: #fff;
  background-image: url('@/assets/images/xiehe/detail/details_bg.png');
}
.infoTag {
  position: relative;
  width: 0px;
  height: 0px;
  border-right: 20px solid #fff;
  border-left: 503px solid #e50021;
  border-top: 19px solid #e50021;
  border-bottom: 19px solid #e50021;
}
.tagText {
  position: absolute;
  left: -480px;
  top: -9.5px;
  max-width: 480px;
  text-overflow: ellipsis;
  color: #fff;
  font-size: 18px;
  overflow: hidden;
  white-space: nowrap;
}
.bookDetail {
  display: flex;
  overflow: hidden;
  margin-top: 30px;
}
.bookImg {
  position: relative;
  width: 338px;
  height: 400px;
  box-shadow: 2px 2px 10px #f2f2f2;
}
.detailBox {
  flex: 1;
  height: 450px;
  position: relative;
  margin-top: 20px;
  overflow: hidden;
}
.collectBox {
  position: absolute;
  right: 80px;
  font-size: 14px;
  color: #999999;
  cursor: pointer;
}
.collectBox span:nth-child(1) {
  margin-right: 10px;
  font-size: 16px;
}
.collectBox span:nth-child(2) {
  margin-left: 10px;
  margin-right: 10px;
  font-size: 16px;
}
.iconfont {
  font-size: 25px !important;
  vertical-align: middle;
}
.bookTitle {
  width: 100%;
  height: 40px;
  line-height: 40px;
  padding-left: 100px;
  display: flex;
  padding-right: 240px;
  box-sizing: border-box;
}
.collectText {
  font-size: 16px;
  line-height: 25px;
  display: inline-block;
}
.bookName {
  flex: 1;
  font-size: 26px;
  color: #333;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.bookTag {
  max-width: 200px;
  font-size: 16px;
  color: #333;
  line-height: 36px;
  margin-left: 15px;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.authorBox {
  width: 80%;
  display: flex;
  padding: 20px;
  padding-left: 100px;
  position: relative;
}
.valueBox {
  margin-left: 20px;
}
.valueBox div {
  height: 30px;
}
.titleBox1 div {
  height: 30px;
}
.relationBox {
  position: absolute;
  right: 50px;
  color: #999;
  cursor: pointer;
  font-size: 14px;
}
.purchaseBox {
  margin-left: 100px;
  padding-top: 20px;
}
.priceBox {
  border-bottom: 1px dashed #ececec;
  background-color: #b2d9c8;
  height: 50px;
  line-height: 50px;
  padding-left: 20px;
}
.priceBox span:nth-child(1) {
  color: #000;
  font-weight: 700;
  font-size: 16px;
  padding-right: 20px;
}
.priceBox span:nth-child(2) {
  color: #e50021;
  font-size: 16px;
}
.priceBox span:nth-child(3) {
  color: #e50021;
  font-size: 22px;
  font-weight: 700;
  padding-right: 20px;
}
.priceBox span:nth-child(4) {
  color: #333;
  font-size: 16px;
  padding-right: 20px;
  text-decoration: line-through;
}
.buyInfo {
  padding: 20px 0px;
  border-bottom: 1px dashed #ececec;
  cursor: pointer;
}
.buyInfo img {
  margin-left: 10px;
}
.btnBox {
  margin-left: 100px;
  margin-top: 30px;
}
.infoItem {
  display: flex;
  margin-top: 40px;
}
.infoImg {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 1px solid #ccc;
  background: #efefef;
  text-align: center;
  line-height: 60px;
  position: relative;
}
.infoImg i {
  font-size: 28px;
}
.infoList {
  margin-top: 20px;
  overflow: auto;
}
.infoContent {
  flex: 1;
  overflow: hidden;
  padding: 0 20px 0 10px;
}
.infoDialog {
  padding: 20px;
}
.infoTitle {
  width: 100%;
  display: flex;
  justify-content: space-between;
}
.infoText {
  margin-top: 24px;
  line-height: 20px;
}
.contactBox {
  padding: 0px 40px;
}
.contacItem {
  margin-top: 20px;
}
.contacIcon {
  padding-right: 20px;
}
.subBtn {
  margin-top: 20px;
  text-align: right;
}
.buyIcon {
  width: 24px;
  height: 24px;
  vertical-align: middle;
}
.crumbs {
  margin-top: 10px;
  border-bottom: 1px solid rgba(20, 73, 65, 0.26);
  padding-bottom: 20px;
}
.detailContent {
  margin-top: 30px;
  .resourceBox {
    width: 80%;
  }
  .textbookInfo {
    padding: 20px 0;
  }
}
.titleBorderBox {
  height: 30px;
  line-height: 30px;
  font-weight: 700;
  border-left: 6px solid #019e58;
  padding-left: 20px;
  font-size: 18px;
}
.textbookInfoItem {
  margin-top: 20px;
}
</style>
src/views/bookStore/index.vue
New file
@@ -0,0 +1,383 @@
<template>
  <div class="homePage">
    <div class="bannerBox imgBox">
      <img class="bannerImg" :src="banner[0]?.icon" @click="bannerLink(item)" />
      <div class="bannerText">
        <div>数字教材</div>
        <div class="enText">ABOUT US</div>
      </div>
    </div>
    <div class="contentBox" style="margin-top: 50px">
      <div class="imgBox">
        <img class="autoimg" src="@/assets/images/bookStore/feblei.png" />
      </div>
      <div class="classificationBox">
        <div style="width: 100px">分类:</div>
        <div class="classificaListBox">
          <div class="classificaItem" v-for="(item, index) in classfeild" :key="index">
            {{ item.name }}
          </div>
        </div>
      </div>
      <div class="bookList">
        <div class="bookfilterList">
          <div class="listTitle">
            <div>结果:共计***条</div>
            <div style="width: 300px">
              <el-input
                v-model="input3"
                placeholder="输入教材名称、作者姓名、出品方名称搜索"
                class="input-with-select"
              >
                <template #append>
                  <el-button :icon="Search" />
                </template>
              </el-input>
            </div>
          </div>
          <div>
            <div class="recommendList">
              <div
                class="recommendItem"
                v-for="item in bookListData"
                :key="item.id"
                @click="toDetail(item)"
              >
                <div class="recommendItemImg">
                  <img class="autoImg" :src="item.icon" />
                </div>
                <div class="infoBox">
                  <div class="bookName">{{ item.name }}</div>
                  <div class="author">
                    作者:{{ item.authorcaupress_author ? item.caupress_author : '-' }}
                  </div>
                  <div class="priceBox">
                    <span class="oldPrice" v-if="item.oldPrice">原价:¥{{ item.oldPrice }}</span>
                    <span class="price" v-if="item.price && item.price > 0">
                      定价:¥
                      <span>{{ item.price }}</span>
                    </span>
                    <span class="price" v-else> 定价:<span class="freePrice">免费</span> </span>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div v-if="!bookListData.length > 0">
            <el-empty class="noData" description="暂无数据" />
          </div>
          <div class="pagingBox">
            <el-pagination
              layout="total, prev, pager, next"
              :total="total"
              v-model:current-page="currentPage1"
              :page-size="20"
              @current-change="handleCurrentChange"
              hide-on-single-page="true"
            />
          </div>
        </div>
        <div class="recommendBox">
          <div class="recommendTitle">推荐教材</div>
          <div class="newRecommendList">
            <div class="recommendItem" v-for="item in bookListData" :key="item.id">
              <div class="recommendItemImg">
                <img class="autoImg" :src="item.icon" />
              </div>
              <div class="infoBox">
                <div class="bookName">{{ item.name }}</div>
                <div class="author">
                  作者:{{ item.authorcaupress_author ? item.caupress_author : '-' }}
                </div>
                <div class="priceBox">
                  <span class="oldPrice" v-if="item.oldPrice">原价:¥{{ item.oldPrice }}</span>
                  <span class="price" v-if="item.price && item.price > 0">
                    定价:¥
                    <span>{{ item.price }}</span>
                  </span>
                  <span class="price" v-else> 定价:<span class="freePrice">免费</span> </span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref, onBeforeMount, inject, reactive, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
const MG = inject('MG')
const toolClass = inject('toolClass')
const banner = reactive([])
const feildList = reactive([])
const classfeild = reactive([])
import { Search } from '@element-plus/icons-vue'
const input3 = ref('')
let bookListData = ref([])
const total = ref(50)
const currentPage1 = ref(1)
const router = useRouter()
const toDetail = (item) => {
  router.push({
    path: '/bookdetail',
    query: {
      bookId: item.id,
    },
  })
}
const getBanner = () => {
  MG.resource
    .getItem({
      path: 'banner\\educationPublishing',
      fields: { link: [] },
      paging: { start: 0, size: 9 },
    })
    .then((res) => {
      banner.push(...res.datas)
      console.log(res.datas)
    })
}
const handleCurrentChange = (val) => {
  currentPage1.value = val
  getBookList()
}
const getBookList = () => {
  MG.store
    .getProductList({
      path: 'recommendedTextbooks',
      paging: {
        start: 0,
        size: 5,
      },
      fields: {
        author: [],
      },
    })
    .then((res) => {
      console.log(res, '推荐教材')
      bookListData.value = res.datas
    })
}
const classifList = () => {
  const query = {
    refCodes: ['digitalTextbooks'],
  }
  MG.resource.getCmsTypeByRefCode(query).then((res) => {
    console.log(res, 'res')
    const types = toolClass.handleTypeList(res)
    const typeData = types[0].cmsTypeLinks[0].children
    feildList.push(...typeData)
    const temp_classfeild = typeData.find((item) => item.typeField.refCode === 'teachingLevel')
      ?.typeField.cfg.option
    classfeild.push({ name: '全部', value: 'all' }, ...temp_classfeild)
    console.log(typeData, 'typeData')
    console.log(classfeild, 'classfeild')
  })
}
onMounted(() => {
  getBanner()
  classifList()
  getBookList()
})
</script>
<style lang="less" scoped>
.homePage {
  min-width: 1220px;
  min-height: calc(100vh - 61.8%);
  background-color: #fff;
  padding-bottom: 100px;
  .bannerBox {
    height: 380px;
    position: relative;
    .bannerText {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      font-size: 36px;
      font-weight: 700;
      color: #fff;
      text-shadow: 0px 0px 10px #000000;
      text-align: center;
    }
    .enText {
      font-size: 36px;
      opacity: 0.45;
      margin-top: 20px;
    }
  }
  .classificationBox {
    display: flex;
    justify-content: space-between;
    margin-top: 30px;
    .classificaListBox {
      display: flex;
      flex-wrap: wrap;
      .classificaItem {
        display: flex;
        align-items: center;
        justify-content: center;
        margin-right: 20px;
        margin-bottom: 20px;
        padding: 10px 16px;
        width: 200px;
        line-height: 20px;
        background: #f5f5f5;
        text-align: center;
      }
    }
  }
  .bookList {
    display: flex;
    justify-content: space-between;
    padding: 20px;
    .bookfilterList {
      width: 80%;
      border: 1px solid #e4e7ed;
      height: 100%;
      border-radius: 10px;
      .listTitle {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 20px 30px;
      }
    }
    .recommendBox {
      width: 19%;
      border: 1px solid #e4e7ed;
      border-radius: 10px;
      .recommendTitle {
        height: 50px;
        line-height: 50px;
        padding-left: 20px;
        border-bottom: 1px solid #e4e7ed;
        color: #333333;
        font-weight: 700;
      }
    }
  }
}
.recommendList {
  display: flex;
  padding: 20px;
  padding-top: 0;
  flex-wrap: wrap;
  justify-content: start;
  .recommendItem {
    margin-right: 20px;
    width: 22%;
    height: 300px;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    cursor: pointer;
    border: 1px solid #dedede;
    background-color: #fff;
    padding-top: 10px;
    margin-top: 10px;
    &:last-child {
      margin-right: 0;
    }
  }
  .recommendItemImg {
    width: 150px;
    height: 200px;
    position: relative;
    margin: 0 auto;
  }
  .infoBox {
    text-align: center;
    margin-top: 10px;
  }
  .author {
    margin-top: 10px;
  }
  .priceBox {
    margin-top: 10px;
    .oldPrice {
      font-size: 16px;
      color: #444444;
      text-decoration: line-through;
      margin-right: 20px;
    }
    .price {
      span {
        font-weight: bold;
        font-size: 14px;
      }
    }
  }
}
.newRecommendList {
  padding-top: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  .recommendItem {
    margin-right: 20px;
    height: 300px;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    cursor: pointer;
    background-color: #fff;
    padding-top: 10px;
    margin-top: 10px;
    &:last-child {
      margin-right: 0;
    }
  }
  .recommendItemImg {
    width: 150px;
    height: 200px;
    position: relative;
    margin: 0 auto;
  }
  .infoBox {
    text-align: center;
    margin-top: 10px;
  }
  .author {
    margin-top: 10px;
  }
  .priceBox {
    margin-top: 10px;
    .oldPrice {
      font-size: 16px;
      color: #444444;
      text-decoration: line-through;
      margin-right: 20px;
    }
    .price {
      span {
        font-weight: bold;
        font-size: 14px;
      }
    }
  }
}
.pagingBox {
  display: flex;
  justify-content: center;
  margin: 20px 0;
  padding-bottom: 30px;
}
</style>
src/views/classManage/classHome.vue
@@ -255,7 +255,7 @@
const Sloading = ref(false)
onMounted(() => {
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userCache: any = localStorage.getItem(config.userInfoKey)
  if (userCache) {
    userInfo.value = JSON.parse(userCache)
  }
src/views/classManage/components/headerPage.vue
@@ -43,7 +43,8 @@
      <WarningFilled />
    </el-icon>
    <p>
      如果您已使用【京师智教扫一扫】或【云上书房】 微信注册过,请使用微信扫码登录;如果您已在【
      如果您已使用【京师智教扫一扫】或【云上书房】
      微信注册过,请使用微信扫码登录;如果您已在【
      京师智教】PC端注册过,请使用手机号登录!继续注册将创建全新账户!
    </p>
    <template #footer>
@@ -55,11 +56,11 @@
</template>
<script setup lang="ts">
import login from '@/layout/components/login.vue'
// import login from '@/layout/components/login.vue'
import { onMounted, ref, watchEffect, inject, watch } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance } from 'element-plus'
import logo from '@/assets/images/header/logo.png'
import titleName from '@/assets/images/header/titleName.png'
// import logo from '@/assets/images/header/logo.png'
// import titleName from '@/assets/images/header/titleName.png'
import { useRouter } from 'vue-router'
import { useUserStore, applyBookStore } from '@/store'
const loginRef = ref()
@@ -67,10 +68,10 @@
const userStore = useUserStore()
const applyBook = applyBookStore()
const MG = inject('MG')
const config = inject('config')
const config:any = inject('config')
const tipsDialogState = ref<boolean>(false) // 温馨提示弹窗状态
const wechatTipsState = ref<boolean>(false)
const localData = ref(localStorage.getItem('jsek-token'))
const localData = ref(localStorage.getItem(config.tokenKey))
onMounted(() => {
  // 判断是否微信扫码登录
  var url = window.location.href
@@ -109,7 +110,7 @@
  }
})
watchEffect(() => {
  localData.value = localStorage.getItem('jsek-token') || '0'
  localData.value = localStorage.getItem(config.tokenKey) || '0'
})
// 注册按钮
@@ -153,7 +154,6 @@
const goHome = () => {
  router.push('/home')
}
</script>
<style lang="less">
@@ -194,8 +194,8 @@
      font-size: 24px;
      padding: 0 10px;
      margin-left: 15px;
      border-left: 1px solid #C0C0C0;
      color:#181818;
      border-left: 1px solid #c0c0c0;
      color: #181818;
      font-family: Microsoft YaHei, Microsoft YaHei;
      font-weight: 400;
    }
src/views/classManage/index.vue
@@ -29,7 +29,7 @@
            >
              <span
                :style="{
                  fill: activeIndex == index ? '#fff' : '#000'
                  fill: activeIndex == index ? '#fff' : '#000',
                }"
                v-html="item.icon"
              >
@@ -50,115 +50,120 @@
</template>
<script setup lang="ts">
import { ref, watch, provide, onMounted, inject } from 'vue'
import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router'
import Header from './components/headerPage.vue'
import { menu } from './config'
import { getPublicImage } from '@/assets/js/middleGround/tool.js'
import defaultImg from '@/assets/images/default-book-img.png'
import { ref, watch, provide, onMounted, inject } from "vue";
import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router";
import Header from "./components/headerPage.vue";
import { menu } from "./config";
import { getPublicImage } from "@/assets/js/middleGround/tool.js";
import defaultImg from "@/assets/images/default-book-img.png";
const router: any = useRouter()
const route: any = useRoute()
const MG: any = inject('MG')
const config: any = inject('config')
const routerVal = router.currentRoute.value
const path = ref(routerVal.path)
const label = ref('')
const classInfo: any = ref()
const classIcon: any = ref()
const listMenu = ref([])
const activeIndex = ref(0)
const userData = ref()
const router: any = useRouter();
const route: any = useRoute();
const MG: any = inject("MG");
const config: any = inject("config");
const routerVal = router.currentRoute.value;
const path = ref(routerVal.path);
const label = ref("");
const classInfo: any = ref();
const classIcon: any = ref();
const listMenu = ref([]);
const activeIndex = ref(0);
const userData = ref();
watch(router.currentRoute, (val) => {
  path.value = val.path
  path.value = val.path;
  if (val.query.classInfo) {
    const data: any = val.query.classInfo
    const routerInfo: any = JSON.parse(data)
    activeIndex.value = routerInfo.index
    const data: any = val.query.classInfo;
    const routerInfo: any = JSON.parse(data);
    activeIndex.value = routerInfo.index;
  }
})
});
watch(classInfo, (val) => {
  if (val) {
    activeIndex.value = val.index
    activeIndex.value = val.index;
  }
  if (!val.index) {
    activeIndex.value = 0
    activeIndex.value = 0;
  }
})
});
onBeforeRouteUpdate(async (to, from) => {
  path.value = to.path
})
  path.value = to.path;
});
onMounted(() => {
  classInfo.value = JSON.parse(route.query.classInfo)
  classIcon.value = classInfo.value.icon ? getPublicImage(classInfo.value.icon, 200) : defaultImg
  classInfo.value = JSON.parse(route.query.classInfo);
  classIcon.value = classInfo.value.icon
    ? getPublicImage(classInfo.value.icon, 200)
    : defaultImg;
  menu.forEach((item) => {
    if ('/' + item.path === path.value) {
      label.value = item.label
    if ("/" + item.path === path.value) {
      label.value = item.label;
    }
  })
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userInfo = JSON.parse(userCache)
  userData.value = userInfo
  });
  const userCache: any = localStorage.getItem(config.userInfoKey);
  const userInfo = JSON.parse(userCache);
  userData.value = userInfo;
  if (!userInfo) {
    router.push({
      path: '/'
    })
    return false
      path: "/",
    });
    return false;
  }
  if (userInfo.role != 'Teacher') {
  if (userInfo.role != "Teacher") {
    const data: any = menu.filter(
      (item: any) => item.path != 'studentManage' && item.path != 'jobAnalysis'
    )
    listMenu.value = data
      (item: any) => item.path != "studentManage" && item.path != "jobAnalysis"
    );
    listMenu.value = data;
  } else {
    const data: any = menu
    const data: any = menu;
    // if (!classInfo.bookRefCode) {
    //   // 融媒体图书,无数字阅读,无法跳转
    //   const list: any = menu.filter((item: any) => item.path != 'teachingPlan')
    //   listMenu.value = list;
    //   return false
    // }
    listMenu.value = data
    listMenu.value = data;
  }
})
});
const goRouter = (item: any, index: number) => {
  activeIndex.value = index
  if (!localStorage.getItem('jsek-token') || localStorage.getItem('jsek-token') == null) {
  activeIndex.value = index;
  if (
    !localStorage.getItem(config.tokenKey) ||
    localStorage.getItem(config.tokenKey) == null
  ) {
    router.push({
      path: '/home',
      path: "/home",
      query: {
        showLogin: '1'
      }
    })
        showLogin: "1",
      },
    });
  } else {
    label.value = item.label
    classInfo.value.index = index
    label.value = item.label;
    classInfo.value.index = index;
    if (item.key == 5) {
      router.push({
        path: userData.value.role != 'Teacher' ? '/studentJob' : '/jobManage',
        path: userData.value.role != "Teacher" ? "/studentJob" : "/jobManage",
        query: {
          classInfo: JSON.stringify(classInfo.value)
        }
      })
          classInfo: JSON.stringify(classInfo.value),
        },
      });
    } else {
      router.push({
        path: item.path,
        query: {
          classInfo: JSON.stringify(classInfo.value)
        }
      })
          classInfo: JSON.stringify(classInfo.value),
        },
      });
    }
  }
}
};
const goBack = () => {
  router.go(-1)
}
  router.go(-1);
};
</script>
<style lang="less" scoped>
src/views/classManage/jobManage.vue
@@ -638,7 +638,7 @@
const pubValue = ref(null)
onMounted(() => {
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userCache: any = localStorage.getItem(config.userInfoKey)
  if (userCache) {
    userInfo.value = JSON.parse(userCache)
  }
src/views/classManage/studentJob.vue
@@ -151,7 +151,7 @@
const tableData: any = ref([])
onMounted(() => {
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userCache: any = localStorage.getItem(config.userInfoKey)
  if (userCache) {
    userInfo.value = JSON.parse(userCache)
  }
src/views/classManage/talkDetail.vue
@@ -135,7 +135,7 @@
const childLoading = ref(false)
onMounted(() => {
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userCache: any = localStorage.getItem(config.userInfoKey)
  if (userCache) {
    userInfo.value = JSON.parse(userCache)
  }
@@ -148,7 +148,7 @@
}
const submitText = (val: string) => {
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userCache: any = localStorage.getItem(config.userInfoKey)
  const userInfo = JSON.parse(userCache)
  if (userInfo?.data) {
    const iconData = JSON.parse(userInfo.data)
src/views/classManage/talkingPoint.vue
@@ -145,7 +145,7 @@
})
onMounted(() => {
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userCache: any = localStorage.getItem(config.userInfoKey)
  if (userCache) {
    userInfo.value = JSON.parse(userCache)
  }
@@ -215,7 +215,7 @@
}
const newTalkMessage = () => {
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userCache: any = localStorage.getItem(config.userInfoKey)
  const userInfo = JSON.parse(userCache)
  const textObj = {
    content: talkContent.value,
src/views/classManage/teachInteraction.vue
@@ -118,7 +118,7 @@
const defaultCmsPath = ref('')
onMounted(() => {
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const userCache: any = localStorage.getItem(config.userInfoKey)
  if (userCache) {
    userInfo.value = JSON.parse(userCache)
  }
src/views/classManage/teachingPlan.vue
@@ -12,7 +12,11 @@
        <div class="titleBox">
          <div class="titleOptions">
            <span>教学计划</span>
            <el-button v-if="userInfo?.role == 'Teacher'" @click="openPlan()" type="primary" round
            <el-button
              v-if="userInfo?.role == 'Teacher'"
              @click="openPlan()"
              type="primary"
              round
              >新建 <el-icon style="margin-left: 3px"><Plus /></el-icon
            ></el-button>
          </div>
@@ -25,7 +29,12 @@
              @keydown.enter="searchData()"
            >
              <template #append>
                <el-button type="primary" @click="searchData()" class="searchBtn" :icon="Search" />
                <el-button
                  type="primary"
                  @click="searchData()"
                  class="searchBtn"
                  :icon="Search"
                />
              </template>
            </el-input>
          </div>
@@ -71,7 +80,7 @@
                    v-for="(item, index) in scope.row.datas.uploadResources"
                    :key="index"
                  >
                    {{ item.FileName + '.' + item.Extension }}
                    {{ item.FileName + "." + item.Extension }}
                  </span>
                </div>
              </template>
@@ -131,7 +140,12 @@
            </el-col>
            <el-col :span="20">
              <div class="grid-content ep-bg-purple-light" />
              <el-input v-model="taskItem.title" placeholder="请填写名称" size="large" clearable />
              <el-input
                v-model="taskItem.title"
                placeholder="请填写名称"
                size="large"
                clearable
              />
            </el-col>
          </el-row>
          <el-row>
@@ -160,7 +174,12 @@
                </el-cascader>
              </div>
              <div class="btngroup">
                <el-button type="primary" @click="addGroup" style="height: 40px" :icon="Plus" />
                <el-button
                  type="primary"
                  @click="addGroup"
                  style="height: 40px"
                  :icon="Plus"
                />
                <el-button
                  type="warning"
                  :disabled="dynamicList.length == 1"
@@ -192,7 +211,12 @@
                  ></el-input>
                </div>
                <div class="btngroup">
                  <el-button type="primary" @click="addGroup" style="height: 40px" :icon="Plus" />
                  <el-button
                    type="primary"
                    @click="addGroup"
                    style="height: 40px"
                    :icon="Plus"
                  />
                  <el-button
                    type="warning"
                    :disabled="dynamicList.length == 1"
@@ -222,7 +246,13 @@
                  >上传</el-button
                >
              </el-upload> -->
              <el-upload class="upload" drag action="#" multiple :http-request="fileUpload">
              <el-upload
                class="upload"
                drag
                action="#"
                multiple
                :http-request="fileUpload"
              >
                <el-icon class="el-icon--upload"><upload-filled /></el-icon>
                <div class="el-upload__text">拖拽或点击文件上传</div>
              </el-upload>
@@ -276,112 +306,112 @@
</template>
<script setup lang="ts">
import { Search, ArrowRight, Plus, Minus } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { reactive, ref, onMounted, inject, watch } from 'vue'
import { useRoute } from 'vue-router'
import axios from 'axios'
import { Search, ArrowRight, Plus, Minus } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { reactive, ref, onMounted, inject, watch } from "vue";
import { useRoute } from "vue-router";
import axios from "axios";
const route: any = useRoute()
const MG: any = inject('MG')
const config: any = inject('config')
const tool: any = inject('toolClass')
const classInfo = JSON.parse(route.query.classInfo)
const userInfo = ref()
const searchKey = ref('')
const visible = ref(false)
const dynamicList: any = ref([])
const tableData: any = ref([])
const classItem = ref([])
const fileList: any = ref([])
const chapterList: any = ref([])
const childrenList: any = ref([])
const taskData: any = ref()
const route: any = useRoute();
const MG: any = inject("MG");
const config: any = inject("config");
const tool: any = inject("toolClass");
const classInfo = JSON.parse(route.query.classInfo);
const userInfo = ref();
const searchKey = ref("");
const visible = ref(false);
const dynamicList: any = ref([]);
const tableData: any = ref([]);
const classItem = ref([]);
const fileList: any = ref([]);
const chapterList: any = ref([]);
const childrenList: any = ref([]);
const taskData: any = ref();
// 新建教学计划防抖
const newLoading = ref(false)
const teachPlanvalue = ref('')
const newLoading = ref(false);
const teachPlanvalue = ref("");
const taskItem = reactive({
  title: '',
  selectChapter: '',
  referenceMaterial: '',
  explain: '',
  uploadResources: ''
})
  title: "",
  selectChapter: "",
  referenceMaterial: "",
  explain: "",
  uploadResources: "",
});
let pages = reactive({
  page: 1,
  pageSize: 13,
  count: 0,
  loading: false
})
  loading: false,
});
onMounted(() => {
  const list = [{ key: 1, parentVal: '', childVal: '' }]
  dynamicList.value = list
  const userCache: any = localStorage.getItem('jesk-userInfo')
  const list = [{ key: 1, parentVal: "", childVal: "" }];
  dynamicList.value = list;
  const userCache: any = localStorage.getItem(config.userInfoKey);
  if (userCache) {
    userInfo.value = JSON.parse(userCache)
    userInfo.value = JSON.parse(userCache);
  }
  pages.loading = true
  getTaskList()
})
  pages.loading = true;
  getTaskList();
});
const searchData = () => {
  pages.page = 1
  getTaskCmsList()
}
  pages.page = 1;
  getTaskCmsList();
};
const openPlan = () => {
  visible.value = true
  taskItem.title = ''
  taskItem.selectChapter = ''
  taskItem.referenceMaterial = ''
  taskItem.explain = ''
  taskItem.uploadResources = ''
  dynamicList.value = [{ key: 1, parentVal: '', childVal: '' }]
  fileList.value = []
}
  visible.value = true;
  taskItem.title = "";
  taskItem.selectChapter = "";
  taskItem.referenceMaterial = "";
  taskItem.explain = "";
  taskItem.uploadResources = "";
  dynamicList.value = [{ key: 1, parentVal: "", childVal: "" }];
  fileList.value = [];
};
const reduceGroup = () => {
  dynamicList.value.pop()
}
  dynamicList.value.pop();
};
const addGroup = () => {
  const source = dynamicList.value[dynamicList.value.length - 1]
  const obj = { key: source.key++, parentVal: '', childVal: '' }
  dynamicList.value.push(obj)
}
  const source = dynamicList.value[dynamicList.value.length - 1];
  const obj = { key: source.key++, parentVal: "", childVal: "" };
  dynamicList.value.push(obj);
};
const handleSizeChange = (val: number) => {
  pages.pageSize = val
  getTaskCmsList()
}
  pages.pageSize = val;
  getTaskCmsList();
};
const handleCurrentChange = (val: number) => {
  pages.page = val
  getTaskCmsList()
}
  pages.page = val;
  getTaskCmsList();
};
// 新建任务
const newTask = () => {
  const data = {
    name: classInfo?.name + '教学计划',
    description: '',
    icon: '',
    name: classInfo?.name + "教学计划",
    description: "",
    icon: "",
    type: config.taskType.teachingPlan,
    state: 'Normal',
    state: "Normal",
    groupId: classInfo?.id,
    order: 0,
    beginDate: '2024-09-09T03:38:07.167Z',
    endDate: '2024-09-09T03:38:07.167Z',
    duration: 0
  }
    beginDate: "2024-09-09T03:38:07.167Z",
    endDate: "2024-09-09T03:38:07.167Z",
    duration: 0,
  };
  MG.edu
    .newTask(data)
    .then((res: any) => {})
    .catch((e: any) => {
      console.log(e)
    })
}
      console.log(e);
    });
};
// 获取任务列表
const getTaskList = () => {
@@ -391,33 +421,33 @@
    filterList: [
      {
        value: config.taskType.teachingPlan,
        field: 'Type',
        subFilters: []
      }
        field: "Type",
        subFilters: [],
      },
    ],
    searchList: [],
    groupId: classInfo?.id
  }
    groupId: classInfo?.id,
  };
  MG.edu
    .getTaskList(data)
    .then((res: any) => {
      if (res.datas.length == 0 && userInfo.value.role == 'Teacher') {
        newTask()
      if (res.datas.length == 0 && userInfo.value.role == "Teacher") {
        newTask();
      }
      if (res.datas.length > 0) {
        taskData.value = res.datas[0]
        classInfo.taskId = taskData.value?.id
        classInfo.rootTaskCmsId = taskData.value?.rootCmsItemId
        taskData.value = res.datas[0];
        classInfo.taskId = taskData.value?.id;
        classInfo.rootTaskCmsId = taskData.value?.rootCmsItemId;
      }
      getTypeByCode()
      getTypeByCode();
      if (classInfo.bookRefCode) {
        getCatalogueList()
        getCatalogueList();
      }
    })
    .catch((e: any) => {
      console.log(e)
    })
}
      console.log(e);
    });
};
// 前往阅读器
const toRead = (item: any) => {
@@ -426,35 +456,35 @@
  if (classInfo.bookRefCode) {
    const url =
      config.textReaderUrl +
      '?bookId=' +
      "?bookId=" +
      classInfo?.bookRefCode +
      '&token=' +
      localStorage.getItem('jsek-token') +
      '&chapter=' +
      "&token=" +
      localStorage.getItem(config.tokenKey) +
      "&chapter=" +
      item.parentVal +
      '&startPage=' +
      item.childVal
    window.open(url, '_blank')
      "&startPage=" +
      item.childVal;
    window.open(url, "_blank");
  } else {
    ElMessage.warning('当前章节无法跳转')
    ElMessage.warning("当前章节无法跳转");
  }
}
};
// 下载上传资源
const downloadRes = (item: any) => {
  const url = config.requestCtx + '/file/api/ApiDownload?md5=' + item.Md5
  window.open(url, '_blank')
}
  const url = config.requestCtx + "/file/api/ApiDownload?md5=" + item.Md5;
  window.open(url, "_blank");
};
// 选择器
const parentSelect = (val: any, item: any) => {
  if (val?.length) {
    const str = val[2]
    const obj = findObj(chapterList.value, str)
    item.parentVal = obj.chapter
    item.childVal = obj.start
    const str = val[2];
    const obj = findObj(chapterList.value, str);
    item.parentVal = obj.chapter;
    item.childVal = obj.start;
  }
}
};
// 文件上传
const fileUpload = (file: any) => {
@@ -469,104 +499,105 @@
    //   ElMessage.error('上传文件大小不能超过 300KB!')
    //   return reject()
    // }
    const FileName = file.file.name.split('.')[0]
    const Extension = file.file.name.split('.')[1]
    const FileType = file.file.type
    let size = 1024
    const FileName = file.file.name.split(".")[0];
    const Extension = file.file.name.split(".")[1];
    const FileType = file.file.type;
    let size = 1024;
    tool
      .getFileMd5(file.file, size * 1024)
      .then((e: string) => {
        if (!fileList.value.find((item: any) => item.md5 == e)) {
          const imgData = new FormData()
          imgData.append('Md5', e)
          imgData.append('FileName', FileName)
          imgData.append('Extension', Extension)
          imgData.append('FileType', FileType)
          imgData.append('MetaData', null)
          imgData.append('file', file.file)
          const imgData = new FormData();
          imgData.append("Md5", e);
          imgData.append("FileName", FileName);
          imgData.append("Extension", Extension);
          imgData.append("FileType", FileType);
          imgData.append("MetaData", null);
          imgData.append("file", file.file);
          MG.file.upload(imgData).then(() => {
            fileList.value.push({
              md5: e,
              linkType: 'LinkFile',
              linkProtectType: 'Public',
              linkType: "LinkFile",
              linkProtectType: "Public",
              fileName: FileName,
              extension: Extension,
              url: config.requestCtx + `​/file​/api​/ApiDownload?md5=` + e
            })
          })
              url: config.requestCtx + `​/file​/api​/ApiDownload?md5=` + e,
            });
          });
        } else {
          ElMessage.warning('当前文件已上传,请勿重复操作!')
          ElMessage.warning("当前文件已上传,请勿重复操作!");
        }
      })
      .catch((e: any) => {
        console.error(e)
      })
  })
}
        console.error(e);
      });
  });
};
// 获取章节目录
const getCatalogueList = () => {
  const url = config.requestCtx + '/books/resource/' + classInfo?.bookRefCode + '/information.json'
  const url =
    config.requestCtx + "/books/resource/" + classInfo?.bookRefCode + "/information.json";
  axios
    .get(url)
    .then((res) => {
      if (res.data?.data.length > 0) {
        const datas = res.data.data
        const list = datas?.filter((item: any) => item.children?.length > 0)
        chapterList.value = changeCascaderData(list)
        const datas = res.data.data;
        const list = datas?.filter((item: any) => item.children?.length > 0);
        chapterList.value = changeCascaderData(list);
      }
    })
    .catch((e) => {
      console.log(e)
    })
}
      console.log(e);
    });
};
// 递归更数组
const changeCascaderData = (data: any) => {
  for (const item of data) {
    item.value = item.start
    item.value = item.start;
    if (item.children?.length > 0) {
      changeCascaderData(item.children)
      changeCascaderData(item.children);
    }
  }
  return data
}
  return data;
};
// 递归查找
const findObj = (arr: any, val: any) => {
  for (let i = 0; i < arr.length; i++) {
    const obj = arr[i]
    const obj = arr[i];
    if (obj.start === val) {
      return obj // 找到目标对象,直接返回
      return obj; // 找到目标对象,直接返回
    }
    if (obj.children && obj.children.length > 0) {
      // 如果当前对象有子对象,递归查找子对象
      const found: any = findObj(obj.children, val)
      const found: any = findObj(obj.children, val);
      if (found) {
        return found // 在子对象中找到目标对象,返回
        return found; // 在子对象中找到目标对象,返回
      }
    }
  }
  return null
}
  return null;
};
// 获取类型字段
const getTypeByCode = () => {
  MG.resource
    .getCmsTypeByRefCode({
      refCodes: [config.refCodes.teachingPlan]
      refCodes: [config.refCodes.teachingPlan],
    })
    .then((res: any) => {
      const data = res[0]?.cmsTypeLinks[0]?.children
      const data = res[0]?.cmsTypeLinks[0]?.children;
      if (data?.length) {
        classItem.value = data
        classItem.value = data;
      }
      getTaskCmsList()
      getTaskCmsList();
    })
    .catch((err: any) => {
      console.log(err)
    })
}
      console.log(err);
    });
};
// 获取任务下的资源列表
const getTaskCmsList = () => {
@@ -577,80 +608,81 @@
      ? [
          {
            keywords: searchKey.value,
            field: 'Name',
            compareType: 'Contains'
          }
            field: "Name",
            compareType: "Contains",
          },
        ]
      : [],
    taskId: classInfo?.taskId,
    path: String(classInfo?.rootTaskCmsId),
    type: '*',
    keys: ['referenceMaterial', 'Name', 'selectChapter', 'uploadResources', 'explain']
  }
    type: "*",
    keys: ["referenceMaterial", "Name", "selectChapter", "uploadResources", "explain"],
  };
  MG.edu
    .getTaskCmsItem(data)
    .then((res: any) => {
      pages.loading = false
      pages.count = res.totalSize
      pages.loading = false;
      pages.count = res.totalSize;
      for (let i = 0; i < res.datas.length; i++) {
        const item = res.datas[i]
        const item = res.datas[i];
        // 处理字段
        if (taskItem != null) {
          for (let fieldKey in taskItem) {
            if (item.datas[fieldKey]) {
              const values = JSON.parse(item.datas[fieldKey])
              const values = JSON.parse(item.datas[fieldKey]);
              if (values.length > 0) {
                // 用字段名处理返回的字段值
                if (values[0].Value) {
                  item.datas[fieldKey] = values[0].Value
                  item.datas[fieldKey] = values[0].Value;
                } else if (values[0].Data) {
                  item.datas[fieldKey] = values[0].Data.Value
                  item.datas[fieldKey] = values[0].Data.Value;
                } else if (!values[0].Value && values[0].FileList?.length > 0) {
                  item.datas[fieldKey] = values[0].FileList
                  item.datas[fieldKey] = values[0].FileList;
                } else {
                  item.datas[fieldKey] = '-'
                  item.datas[fieldKey] = "-";
                }
                if (fieldKey == 'selectChapter' && values[0].Value) {
                  const data = JSON.parse(values[0].Value)
                  item.datas['selectChapter'] = data.map((citem: any) => {
                if (fieldKey == "selectChapter" && values[0].Value) {
                  const data = JSON.parse(values[0].Value);
                  item.datas["selectChapter"] = data.map((citem: any) => {
                    if (classInfo.bookRefCode) {
                      const dataS = findObj(chapterList.value, citem.childVal)
                      const dataS = findObj(chapterList.value, citem.childVal);
                      return {
                        ...citem,
                        parentName:
                          chapterList.value.find((sitem: any) => sitem.chapter == citem.parentVal)
                            ?.label +
                          '---' +
                          dataS?.label
                      }
                          chapterList.value.find(
                            (sitem: any) => sitem.chapter == citem.parentVal
                          )?.label +
                          "---" +
                          dataS?.label,
                      };
                    } else {
                      return {
                        ...citem,
                        parentName: citem.parentVal + '---' + citem.childVal
                      }
                        parentName: citem.parentVal + "---" + citem.childVal,
                      };
                    }
                  })
                  });
                }
                if (fieldKey == 'selectChapter' && !values[0].Value) {
                  item.datas['selectChapter'] = []
                if (fieldKey == "selectChapter" && !values[0].Value) {
                  item.datas["selectChapter"] = [];
                }
              }
              const index = i
              item.datas['index'] = index + 1
              const index = i;
              item.datas["index"] = index + 1;
            }
          }
        }
      }
      tableData.value = res.datas
      tableData.value = res.datas;
    })
    .catch((e: any) => {
      ElMessage({
        message: '列表获取失败',
        type: 'error'
      })
      console.log(e)
    })
}
        message: "列表获取失败",
        type: "error",
      });
      console.log(e);
    });
};
// 删除资源
const removeTaskItem = (item: any) => {
@@ -659,56 +691,56 @@
    requests: [
      {
        cmsItemId: item.id,
        path: String(classInfo?.rootTaskCmsId)
      }
    ]
  }
        path: String(classInfo?.rootTaskCmsId),
      },
    ],
  };
  MG.edu
    .removeTaskCmsItemList(data)
    .then((res: any) => {
      if (res) {
        ElMessage({
          message: '删除成功',
          type: 'success'
        })
        getTaskCmsList()
          message: "删除成功",
          type: "success",
        });
        getTaskCmsList();
      }
    })
    .catch((e: any) => {
      ElMessage({
        message: '删除失败',
        type: 'error'
      })
    })
}
        message: "删除失败",
        type: "error",
      });
    });
};
// 为任务新建资源
const newTaskCmsItems = () => {
  newLoading.value = true
  taskItem.selectChapter = JSON.stringify(dynamicList.value)
  newLoading.value = true;
  taskItem.selectChapter = JSON.stringify(dynamicList.value);
  if (!taskItem.title) {
    ElMessage({
      message: '请填写教学名称',
      type: 'warning'
    })
    newLoading.value = false
    return false
      message: "请填写教学名称",
      type: "warning",
    });
    newLoading.value = false;
    return false;
  }
  if (dynamicList.value[0]?.parentVal == '') {
  if (dynamicList.value[0]?.parentVal == "") {
    ElMessage({
      message: '请选择教学章节',
      type: 'warning'
    })
    newLoading.value = false
    return false
      message: "请选择教学章节",
      type: "warning",
    });
    newLoading.value = false;
    return false;
  }
  if (fileList.value.length == 0) {
    ElMessage({
      message: '请上传教学文件',
      type: 'warning'
    })
    newLoading.value = false
    return false
      message: "请上传教学文件",
      type: "warning",
    });
    newLoading.value = false;
    return false;
  }
  const data = {
    groupId: classInfo?.id,
@@ -717,29 +749,33 @@
    newGroupCmsItemRequests: [
      {
        name: taskItem.title,
        description: '',
        icon: '',
        description: "",
        icon: "",
        type: config.refCodes.teachingPlan,
        state: 'Normal',
        state: "Normal",
        order: 0,
        newDataListRequest: tool.worksDataBytool(classItem.value, taskItem, fileList.value),
        newDataListRequest: tool.worksDataBytool(
          classItem.value,
          taskItem,
          fileList.value
        ),
        newCmsItemAndFileLinkListRequest: [],
        newChildrenListRequest: []
      }
    ]
  }
        newChildrenListRequest: [],
      },
    ],
  };
  MG.edu.newTaskCmsItem(data).then((res: any) => {
    newLoading.value = false
    newLoading.value = false;
    if (res) {
      ElMessage({
        message: '新建成功',
        type: 'success'
      })
      visible.value = false
      getTaskCmsList()
        message: "新建成功",
        type: "success",
      });
      visible.value = false;
      getTaskCmsList();
    }
  })
}
  });
};
// // 编辑资源
// const editOpen = (item: any) => {
src/views/educationalPublishing/index.vue
New file
@@ -0,0 +1,43 @@
<template>
  <div class="homePage">
    <el-carousel :height="screenheight + 'px'">
      <el-carousel-item v-for="(item, index) in banner" :key="index">
        <div class="bannerBox imgBox">
          <img id="autoHeight" class="bannerImg" :src="item.icon" @click="bannerLink(item)" />
        </div>
      </el-carousel-item>
    </el-carousel>
  </div>
</template>
<script setup>
import { ref, onBeforeMount, inject, reactive, onMounted } from 'vue'
const MG = inject('MG')
let screenheight = ref(document.documentElement.clientHeight / 2)
const banner = reactive([])
const getBanner = () => {
  MG.resource
    .getItem({
      path: 'banner\\homeBanner',
      fields: { link: [] },
      paging: { start: 0, size: 9 },
    })
    .then((res) => {
      banner.push(...res.datas)
      console.log(res.datas)
    })
}
onMounted(() => {
  getBanner()
})
</script>
<style lang="less" scoped>
.homePage {
  min-width: 1220px;
  min-height: calc(100vh - 61.8%);
  background-color: #fff;
  padding-bottom: 100px;
}
</style>
src/views/home/index.vue
@@ -1,16 +1,175 @@
<template>
  <div class="homePage">
    <el-carousel :height="screenheight">
      <el-carousel-item v-for="item in 4" :key="item">
        <h3 class="small justify-center" text="2xl">{{ item }}</h3>
    <el-carousel :height="screenheight + 'px'">
      <el-carousel-item v-for="(item, index) in banner" :key="index">
        <div class="bannerBox imgBox">
          <img id="autoHeight" class="bannerImg" :src="item.icon" @click="bannerLink(item)" />
        </div>
      </el-carousel-item>
    </el-carousel>
    <div class="contentBox" style="margin-top: 50px">
      <div class="informationBox">
        <div class="bookListTitle">
          <div class="title">新闻资讯</div>
          <div class="more">更多></div>
        </div>
        <div class="informationList">
          <div class="informationItem" v-for="(item, index) in informationList" :key="index">
            <div class="imgBox"><img class="autoImg" :src="item.icon" alt="" /></div>
            <div class="informationContent">
              <div class="informationTitle" :alt="item.name">{{ item.name }}</div>
              <div class="informationDate">{{ moment(item.publishDate).format('YYYY-MM-DD') }}</div>
              <div class="informationText">{{ item.description }}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="bookListBox">
      <div class="contentBox">
        <div class="bookListTitle">
          <div class="title">推荐教材</div>
          <div class="more">更多></div>
        </div>
        <div class="recommendList">
          <div class="recommendItem" v-for="item in bookListData" :key="item.id">
            <div class="recommendItemImg">
              <img class="autoImg" :src="item.icon" />
            </div>
            <div class="infoBox">
              <div class="bookName">{{ item.name }}</div>
              <div class="author">
                作者:{{ item.authorcaupress_author ? item.caupress_author : '-' }}
              </div>
              <div class="priceBox">
                <span class="oldPrice" v-if="item.oldPrice">原价:¥{{ item.oldPrice }}</span>
                <span class="price" v-if="item.price && item.price > 0">
                  定价:¥
                  <span>{{ item.price }}</span>
                </span>
                <span class="price" v-else> 定价:<span class="freePrice">免费</span> </span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="contentBox">
      <div class="funBox">
        <div class="authentication"></div>
        <div class="manual"></div>
      </div>
      <div class="bookListTitle">
        <div class="title" style="display: flex; line-height: 50px">
          <div>新闻资讯</div>
          <div class="titleTabs">
            <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
              <el-tab-pane label="高等职业教材" name="first"> </el-tab-pane>
              <el-tab-pane label="专升本教材" name="second"></el-tab-pane>
              <el-tab-pane label="协和医学院教材" name="third"></el-tab-pane>
            </el-tabs>
          </div>
        </div>
        <div class="more">更多></div>
      </div>
      <div class="recommendList">
        <div class="recommendItem" v-for="item in bookListData" :key="item.id">
          <div class="recommendItemImg">
            <img class="autoImg" :src="item.icon" />
          </div>
          <div class="infoBox">
            <div class="bookName">{{ item.name }}</div>
            <div class="author">
              作者:{{ item.authorcaupress_author ? item.caupress_author : '-' }}
            </div>
            <div class="priceBox">
              <span class="oldPrice" v-if="item.oldPrice">原价:¥{{ item.oldPrice }}</span>
              <span class="price" v-if="item.price && item.price > 0">
                定价:¥
                <span>{{ item.price }}</span>
              </span>
              <span class="price" v-else> 定价:<span class="freePrice">免费</span> </span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue'
let screenheight = ref(document.documentElement.clientHeight / 4)
import moment from 'moment'
import { ref, onBeforeMount, inject, reactive, onMounted } from 'vue'
let screenheight = ref(document.documentElement.clientHeight / 2)
const MG = inject('MG')
const config = inject('config')
const tool = inject('tool')
const banner = reactive([])
const informationList = reactive([])
let bookListData = ref([])
onBeforeMount(() => {
  console.log(document.documentElement.clientWidth / 2.628)
  window.onresize = () => {
    let c = 2.628
    if (document.documentElement.clientWidth >= 1220) {
      screenheight.value = document.documentElement.clientWidth / c
      console.log(document.documentElement.clientWidth / c)
    }
  }
})
onMounted(() => {
  getBanner()
  getInformationList()
  getBookList()
})
const getBookList = () => {
  MG.store
    .getProductList({
      path: 'recommendedTextbooks',
      paging: {
        start: 0,
        size: 5,
      },
      fields: {
        author: [],
      },
    })
    .then((res) => {
      console.log(res, '推荐教材')
      bookListData.value = res.datas
    })
}
const getInformationList = () => {
  MG.resource
    .getItem({
      path: 'information',
      fields: { publishDate: [], content: [] },
      paging: { start: 0, size: 9 },
    })
    .then((res) => {
      informationList.push(...res.datas)
      console.log(res.datas)
    })
}
const getBanner = () => {
  MG.resource
    .getItem({
      path: 'banner\\homeBanner',
      fields: { link: [] },
      paging: { start: 0, size: 9 },
    })
    .then((res) => {
      banner.push(...res.datas)
      console.log(res.datas)
    })
}
</script>
<style lang="less" scoped>
@@ -18,6 +177,7 @@
  min-width: 1220px;
  min-height: calc(100vh - 61.8%);
  background-color: #fff;
  padding-bottom: 100px;
}
.el-carousel__item h3 {
  color: #475669;
@@ -34,4 +194,161 @@
.el-carousel__item:nth-child(2n + 1) {
  background-color: #d3dce6;
}
.informationList {
  display: flex;
  flex-wrap: wrap;
  .informationItem {
    display: flex;
    width: 42%;
    min-height: 100px;
    margin-right: 5%;
    margin-bottom: 20px;
    border: 1px solid #ebebeb;
    border-radius: 10px;
    padding: 10px;
    cursor: pointer;
    .imgBox {
      width: 30%;
      height: 100%;
      position: relative;
    }
    .informationContent {
      width: 70%;
      padding-left: 10px;
      .informationTitle {
        font-size: 14px;
        width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        color: #333333;
        font-weight: bold;
        margin-bottom: 10px;
      }
      .informationDate {
        margin-top: 10px;
      }
      .informationText {
        color: #666666;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        margin-top: 10px;
        display: -webkit-box; /* 将对象作为弹性伸缩盒子模型显示 */
        -webkit-line-clamp: 3; /* 显示的行数 */
        -webkit-box-orient: vertical; /* 设置或检索伸缩盒对象的子元素的排列方式 */
        overflow: hidden; /* 溢出隐藏 */
      }
    }
  }
  .informationItem:hover {
    border: 1px solid #019e58;
  }
}
.bookListBox {
  width: 100%;
  padding: 80px 0;
  margin-top: 30px;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url('@/assets/images/tuijian-bg.png');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
.recommendList {
  display: flex;
  padding-top: 20px;
  .recommendItem {
    flex: 1;
    margin-right: 20px;
    height: 300px;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    cursor: pointer;
    border: 1px solid #dedede;
    background-color: #fff;
    padding-top: 10px;
    &:last-child {
      margin-right: 0;
    }
  }
}
.recommendItemImg {
  width: 150px;
  height: 200px;
  position: relative;
  margin: 0 auto;
}
.infoBox {
  text-align: center;
  margin-top: 10px;
}
.author {
  margin-top: 10px;
}
.priceBox {
  margin-top: 10px;
  .oldPrice {
    font-size: 16px;
    color: #444444;
    text-decoration: line-through;
    margin-right: 20px;
  }
  .price {
    span {
      font-weight: bold;
      font-size: 14px;
    }
  }
}
.funBox {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 60px;
  margin-bottom: 60px;
  .authentication {
    width: 40%;
    height: 80px;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-image: url('@/assets/images/xiehe/home/jiaoshirenzheng.png');
  }
  .manual {
    width: 40%;
    height: 80px;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-image: url('@/assets/images/xiehe/home/jiaoshirenzheng.png');
  }
}
.titleTabs {
  margin-left: 50px;
}
.bookListTitle {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  border-bottom: 1px solid #ebebeb;
  padding-bottom: 20px;
  .title {
    font-size: 20px;
    color: #333333;
    font-weight: bold;
  }
  .more {
    font-size: 14px;
    color: #999999;
    cursor: pointer;
  }
}
</style>
src/views/personalCenter/activeCode.vue
@@ -90,11 +90,10 @@
import moment from "moment";
import { getPublicImage } from "@/assets/js/middleGround/tool.js";
import { ElMessage } from "element-plus";
import { useBreadcrumbStore, useUserStore } from "@/store";
import { useUserStore } from "@/store";
import { useRouter } from "vue-router";
import bookCover from "@/assets/images/personalCenter/book-cover.png";
const router = useRouter();
const crumbStore = useBreadcrumbStore();
const userStore = useUserStore();
const MG = inject("MG");
const activateCode = ref("");
@@ -210,80 +209,27 @@
  let parentData = await MG.store.getProductBySaleMethod({
    saleMethodId: defaultSaleMethodId,
  });
  console.log(parentData, 123);
  if (parentData.storeLinks[0].storeRefCode == "jsek_digitalCourses") {
    let crumbs = [
      {
        name,
        isCrumbs: true,
        type: "digitalCourses",
        path: "digitalCoursesDetails",
      },
    ];
    // 在全局数据中设置面包屑
    crumbStore.setCrumbs({
      type: "digitalCourses",
      data: crumbs,
      callback: (key: any) => {
        router.push({
          name: "digitalCoursesDetails",
          query: {
            crumbsKey: key,
            bookId: parentData.id,
            bookName: parentData.name,
            type: "digitalCourses",
          },
        });
    router.push({
      name: "digitalCoursesDetails",
      query: {
        bookId: parentData.id,
        bookName: parentData.name,
      },
    });
  } else if (parentData.storeLinks[0].storeRefCode == "jsek_digitalTextbooks") {
    let crumbs = [
      {
        name,
        isCrumbs: true,
        type: "digitalTextbooks",
        path: "digitalTextbooksDetails",
      },
    ];
    // 在全局数据中设置面包屑
    crumbStore.setCrumbs({
      type: "digitalTextbooks",
      data: crumbs,
      callback: (key: any) => {
        router.push({
          name: "digitalTextbooksDetails",
          query: {
            crumbsKey: key,
            bookId: parentData.id,
            bookName: parentData.name,
            type: "digitalTextbooks",
          },
        });
    router.push({
      name: "digitalTextbooksDetails",
      query: {
        bookId: parentData.id,
        bookName: parentData.name,
      },
    });
  } else {
    let crumbs = [
      {
        name,
        isCrumbs: true,
        type: "bookService",
        path: "/bookService/details",
      },
    ];
    // 在全局数据中设置面包屑
    crumbStore.setCrumbs({
      type: "bookService",
      data: crumbs,
      callback: (key: any) => {
        router.push({
          name: "bookDetails",
          query: {
            crumbsKey: key,
            bookId: id,
            bookName: name,
            type: "bookService",
          },
        });
    router.push({
      name: "bookdetail",
      query: {
        bookId: id,
      },
    });
  }
src/views/personalCenter/course.vue
@@ -70,7 +70,8 @@
            >
              未通过
            </div>
            <img :src="item.icon" />
            <img v-if="item.icon" :src="item.icon" />
            <img v-else :src="defaultImg" alt="" />
          </div>
          <div class="infoBox">
            <p class="id">ID:{{ item.id }}</p>
@@ -423,11 +424,11 @@
  textBookPages.loading = true;
  const searchData = [
    {
      keywords: "jsek_digitalTextbooks",
      keywords: "digitalTextbooks",
      field: "ProductType",
    },
    {
      keywords: "jsek_mediaBook",
      keywords: "mediaBook",
      field: "ProductType",
    },
    {
@@ -605,8 +606,8 @@
  margin-bottom: 20px;
  .textBookItem {
    float: left;
    width: 140px;
    height: 200px;
    width: 160px;
    height: 220px;
    margin: 10px;
    position: relative;
    border: 1px solid #eee;
@@ -624,12 +625,6 @@
      }
    }
    .imgBox {
      width: 100px;
      height: 110px;
      margin-bottom: 10px;
    }
    p {
      line-height: 1.2;
      display: -webkit-box;
@@ -640,6 +635,25 @@
  }
}
.autoImgBox {
  width: 120px;
  height: 130px;
  margin-bottom: 10px;
  position: relative;
  img {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
  }
}
.pagination-box {
  display: flex;
  justify-content: center;
src/views/personalCenter/index.vue
@@ -41,53 +41,58 @@
</template>
<script setup lang="ts">
import { ArrowRight } from '@element-plus/icons-vue'
import { menu } from './config.ts'
import { useRouter, onBeforeRouteUpdate } from 'vue-router'
import { ref, onMounted } from 'vue'
const router = useRouter()
const routerVal = router.currentRoute.value
const path = ref(routerVal.path)
const label = ref('')
const listMenu: any = ref([])
import { ArrowRight } from "@element-plus/icons-vue";
import { menu } from "./config.ts";
import { useRouter, onBeforeRouteUpdate } from "vue-router";
import { ref, onMounted, inject } from "vue";
const router = useRouter();
const routerVal = router.currentRoute.value;
const path = ref(routerVal.path);
const label = ref("");
const listMenu: any = ref([]);
const MG: any = inject("MG");
const config: any = inject("config");
onBeforeRouteUpdate(async (to, from) => {
  path.value = to.fullPath
})
  path.value = to.fullPath;
});
onMounted(() => {
  menu.forEach((item) => {
    if ('/' + item.path === path.value) {
      label.value = item.label
    if ("/" + item.path === path.value) {
      label.value = item.label;
    }
  })
  // const userCache: any = localStorage.getItem('jesk-userInfo')
  // const userInfo = JSON.parse(userCache)
  // if(!userInfo){
  //   router.push({
  //     path:'/'
  //   })
  //   return false;
  // }
  // if (userInfo.role == 'Teacher') {
  //   const data: any = menu.filter((item) => item.path != 'class')
  //   listMenu.value = data
  // } else {
  const data: any = menu.filter((item) => item.path != 'course')
  listMenu.value = data
  // }
})
  });
  const userCache: any = localStorage.getItem(config.userInfoKey);
  const userInfo = JSON.parse(userCache);
  if (!userInfo) {
    router.push({
      path: "/",
    });
    return false;
  }
  if (userInfo.role == "Teacher") {
    const data: any = menu.filter((item) => item.path != "myClass");
    listMenu.value = data;
  } else {
    const data: any = menu.filter((item) => item.path != "myCourse");
    listMenu.value = data;
  }
});
const goRouter = (item: any) => {
  // if (!localStorage.getItem('jsek-token') || localStorage.getItem('jsek-token') == null) {
  //   router.push({
  //     path: '/home',
  //     query: {
  //       showLogin: '1'
  //     }
  //   })
  // } else {
  label.value = item.label
  router.push({ path: item.path })
  // }
}
  if (
    !localStorage.getItem(config.tokenKey) ||
    localStorage.getItem(config.tokenKey) == null
  ) {
    router.push({
      path: "/home",
      query: {
        showLogin: "1",
      },
    });
  } else {
    label.value = item.label;
    router.push({ path: item.path });
  }
};
</script>
<style lang="less" scoped>
.breadcrumbBox {
src/views/personalCenter/myApply.vue
@@ -117,10 +117,10 @@
<script setup lang="ts">
import { reactive, ref, onMounted, inject } from "vue";
import { getPublicImage } from "@/assets/js/middleGround/tool";
import { useRouter } from "vue-router";
const MG: any = inject("MG");
const config: any = inject("config");
const crumbStore = inject("crumbStore");
const router = inject("router");
const router = useRouter();
let listData = ref([]);
let loading = ref(false);
let paginationData = reactive({
@@ -175,19 +175,11 @@
});
const toDetail = (item: any) => {
  const thisCrumbs = [{ name: "书籍详情", pathName: "digitalTextbooks-textbooksDetail" }];
  MG.store.dispatch("setCrumbs", {
    type: "textbooks",
    data: thisCrumbs,
    callback: (key: string) => {
      MG.router.push({
        name: "digitalTextbooks-textbooksDetail",
        query: {
          id: item.id,
          rootCmsItemId: item.rootCmsItemId,
          crumbsKey: key,
        },
      });
  router.push({
    name: "digitalTextbooks-textbooksDetail",
    query: {
      id: item.id,
      rootCmsItemId: item.rootCmsItemId,
    },
  });
};
src/views/personalCenter/myBook.vue
@@ -11,58 +11,59 @@
            @click="goDetail(item)"
          >
            <div class="imgBox">
              <img :src="item.product.icon" alt />
              <img v-if="item.product.icon" :src="item.product.icon" />
              <img v-else :src="defaultImg" alt="" />
            </div>
            <div class="details">
              <div class="text-flow" v-if="item.product.name">
                {{ item.product.name || "-" }}
              </div>
              <div class="text-flow" :title="item.tourism_ISBN">
                ISBN:{{ item.tourism_ISBN.length != 0 ? item.tourism_ISBN : "-" }}
              <div class="text-flow" :title="item.isbn">
                ISBN:{{ item.isbn.length != 0 ? item.isbn : "-" }}
              </div>
              <div class="text-flow">
                作者:{{ item.tourism_author.length != 0 ? item.tourism_author : "-" }}
                作者:{{ item.author.length != 0 ? item.author : "-" }}
              </div>
              <!-- <div class="text-flow" v-if="item.ExpiryDate">
            截止日期:<span style="color: #dd0000">{{ item.ExpiryDate }}</span>
          </div> -->
            </div>
          </div>
          <div class="pageCon">
            <!-- 分页 -->
            <el-pagination
              background
              :current-page="paginationData.page - 0"
              @size-change="handleSizeChange"
              @current-change="handleCurrentChange"
              :page-size="paginationData.limit"
              layout="total, prev, pager, next, slot"
              :total="paginationData.totalCount"
            >
              <div style="display: inline-block">
                <span class="el-pagination__jump"
                  >前往
                  <div class="el-input el-pagination__editor is-in-pagination">
                    <input
                      type="number"
                      autocomplete="off"
                      min="1"
                      :max="paginationData.totalPage"
                      v-model="inputPage"
                      class="el-input__inner"
                      @keyup.enter="jumpFun($event)"
                    />
                  </div>
                  页
                </span>
                <el-button type="primary" class="toBtn" @click="jumpFun">确定</el-button>
              </div>
            </el-pagination>
          </div>
        </div>
        <div class="myCarTopPage" v-else>
          <el-empty description="您还未购买任何图书" :image-size="200" />
        </div>
      </div>
      <div class="pageCon">
        <!-- 分页 -->
        <el-pagination
          background
          :current-page="paginationData.page - 0"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :page-size="paginationData.limit"
          layout="total, prev, pager, next, slot"
          :total="paginationData.totalCount"
        >
          <div style="display: flex; align-items: center">
            <span class="el-pagination__jump"
              >前往
              <div class="el-input el-pagination__editor is-in-pagination">
                <input
                  type="number"
                  autocomplete="off"
                  min="1"
                  :max="paginationData.totalPage"
                  v-model="inputPage"
                  class="el-input__inner"
                  @keyup.enter="jumpFun($event)"
                />
              </div>
              页
            </span>
            <el-button type="primary" class="toBtn" @click="jumpFun">确定</el-button>
          </div>
        </el-pagination>
      </div>
    </div>
  </div>
@@ -71,12 +72,12 @@
<script lang="ts" setup>
import { reactive, ref, onMounted, inject, watch } from "vue";
import { useRouter } from "vue-router";
import { useUserStore, useBreadcrumbStore } from "@/store";
import defaultImg from "@/assets/images/default-book-img.png";
import { useUserStore } from "@/store";
import tool from "@/assets/js/toolClass";
const MG: any = inject("MG");
const config: any = inject("config");
const router = useRouter();
const crumbStore = useBreadcrumbStore();
let collectList = ref([]);
let currentCollect = ref("book");
let isLoading = ref(false);
@@ -128,7 +129,6 @@
    listData.value.forEach((item) => {
      item.product.icon = tool.getPublicImage(item.product.icon);
    });
    // console.log(that.collectList);
    // //当前页面
    paginationData.totalCount = response.totalSize;
    paginationData.totalPage =
@@ -136,6 +136,7 @@
        ? response.totalSize / paginationData.limit
        : Math.floor(response.totalSize / paginationData.limit) + 1;
    loading.value = false;
    collectList.value = response.datas;
  });
};
onMounted(() => {
@@ -167,23 +168,10 @@
//到图书详情
const goDetail = (item) => {
  let crumbs = [
    {
      name: "教材详情",
    },
  ];
  crumbStore.dispatch("setCrumbs", {
    type: "textbooks",
    data: crumbs,
    callback: (key) => {
      router.push({
        name: "digitalTextbooks-textbooksDetail",
        query: {
          id: item.product.id,
          rootCmsItemId: item.product.rootCmsItemId,
          crumbsKey: key,
        },
      });
  router.push({
    path: "/bookdetail",
    query: {
      bookId: item.product.id,
    },
  });
};
@@ -220,6 +208,8 @@
  justify-content: center;
}
.myCarTopPage {
  display: flex;
  justify-content: flex-start;
  box-sizing: border-box;
  overflow: hidden;
  padding-bottom: 20px;
@@ -268,7 +258,7 @@
}
.bookone {
  display: flex;
  width: 478px;
  width: 420px;
  min-height: 173px;
  float: left;
  cursor: pointer;
src/views/personalCenter/myCart.vue
@@ -35,12 +35,6 @@
          </template>
        </el-dialog>
      </div>
      <div class="breadcrumbsBox">
        <p>
          位置: <span>购物车({{ total }})</span>
        </p>
      </div>
      <div class="selectproduct">
        <el-table
          ref="multipleTableRef"
@@ -79,10 +73,9 @@
          <el-table-column
            property="name"
            label="商品信息"
            width="300"
            :cell-style="{ margin: '30px' }"
            width="200"
          />
          <el-table-column property="productType" label="商品类型" width="300" />
          <el-table-column property="productType" label="商品类型" width="200" />
          <el-table-column label="价格">
            <template #default="scope">¥{{ scope.row.unitprice.toFixed(2) }}</template>
          </el-table-column>
@@ -142,11 +135,10 @@
import { reactive } from "vue";
import { useRouter } from "vue-router";
import { InfoFilled } from "@element-plus/icons-vue";
import { useUserStore, useBreadcrumbStore } from "@/store";
import { useUserStore } from "@/store";
import { getPublicImage } from "@/assets/js/middleGround/tool.js";
import defaultImg from "@/assets/images/default-book-img.png";
const dialogVisible = ref(false);
const crumbStore = useBreadcrumbStore();
const router = useRouter();
const userStore = useUserStore();
const MG = inject("MG");
@@ -332,27 +324,14 @@
      orderNumber.value = createOrderResult.orderNumber;
      if (selectedIds.length) {
        let crumbs = {
          name: "订单支付", // 面包屑名称
          pathName: "paymentPage", // 面包屑跳转路由,可传递 pathName 或 path
          isCrumbs: true, // 面包屑点击跳转时是否创建新的面包屑记录
          type: "shoppingCart", // 如果需要创建新的面包屑记录,创建的type
        };
        // 在全局数据中设置面包屑
        crumbStore.setCrumbs({
          type: "shoppingCart",
          data: [crumbs],
          callback: (key) => {
            router.push({
              name: "paymentPage",
              query: {
                crumbsKey: key,
                orderNumber: orderNumber.value,
                // type: route.query.type,
                type: "shoppingCart",
                onNorderSaleMethod: saleMethodId,
              },
            });
        router.push({
          name: "paymentPage",
          query: {
            crumbsKey: key,
            orderNumber: orderNumber.value,
            // type: route.query.type,
            type: "shoppingCart",
            onNorderSaleMethod: saleMethodId,
          },
        });
      } else {
src/views/personalCenter/myCollection.vue
@@ -68,10 +68,9 @@
<script setup lang="ts">
import { reactive, ref, onMounted, inject, watch } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { useBreadcrumbStore, useUserStore } from '@/store'
import { useUserStore } from "@/store";
import { useRouter } from "vue-router";
const crumbStore = useBreadcrumbStore()
const userStore = useUserStore()
const userStore = useUserStore();
const router = useRouter();
const MG: any = inject("MG");
const config: any = inject("config");
@@ -161,51 +160,10 @@
};
// 跳转书本详情
const goBookDetails = (id: number, name: string) => {
  let crumbs = [
    {
      name,
      isCrumbs: true,
      type:
        currentCollect.value == "book"
          ? "bookService"
          : currentCollect.value == "textBooks"
          ? "digitalTextbooks"
          : "digitalCourses",
      path:
        currentCollect.value == "book"
          ? "/bookService/details"
          : "/digitalCoursesDetails",
    },
  ];
  // 在全局数据中设置面包屑
  crumbStore.setCrumbs({
    type:
      currentCollect.value == "book"
        ? "bookService"
        : currentCollect.value == "textBooks"
        ? "digitalTextbooks"
        : "digitalCourses",
    data: crumbs,
    callback: (key: any) => {
      router.push({
        name:
          currentCollect.value == "book"
            ? "bookDetails"
            : currentCollect.value == "textBooks"
            ? "digitalTextbooksDetails"
            : "digitalCoursesDetails",
        query: {
          crumbsKey: key,
          bookId: id,
          bookName: name,
          type:
            currentCollect.value == "book"
              ? "bookService"
              : currentCollect.value == "textBooks"
              ? "digitalTextbooks"
              : "digitalCourses",
        },
      });
  router.push({
    path: "/bookdetail",
    query: {
      bookId: id,
    },
  });
};
src/views/personalCenter/myOrder.vue
@@ -149,10 +149,9 @@
import { ElMessage } from "element-plus";
import { getPublicImage } from "@/assets/js/middleGround/tool.js";
import { useRouter } from "vue-router";
import { useBreadcrumbStore, useUserStore } from "@/store";
import { useUserStore } from "@/store";
import bookCover from "@/assets/images/personalCenter/book-cover.png";
const router = useRouter();
const crumbStore = useBreadcrumbStore();
const userStore = useUserStore();
const MG: any = inject("MG");
let order = ref("all");
@@ -239,53 +238,17 @@
  let parentData = null;
  let bookId = id;
  if (refCode == "digitalCourses") {
    let crumbs = [
      {
        name,
        isCrumbs: true,
        type: "digitalCourses",
        path: "digitalCoursesDetails",
      },
    ];
    // 在全局数据中设置面包屑
    crumbStore.setCrumbs({
      type: "digitalCourses",
      data: crumbs,
      callback: (key: any) => {
        router.push({
          name: "digitalCoursesDetails",
          query: {
            crumbsKey: key,
            bookId: bookId,
            bookName: name,
            type: "digitalCourses",
          },
        });
    router.push({
      path: "/bookdetail",
      query: {
        bookId: bookId,
      },
    });
  } else if (refCode == "digitalTextbooks") {
    let crumbs = [
      {
        name,
        isCrumbs: true,
        type: "digitalTextbooks",
        path: "digitalTextbooksDetails",
      },
    ];
    // 在全局数据中设置面包屑
    crumbStore.setCrumbs({
      type: "digitalTextbooks",
      data: crumbs,
      callback: (key: any) => {
        router.push({
          name: "digitalTextbooksDetails",
          query: {
            crumbsKey: key,
            bookId: bookId,
            bookName: name,
            type: "digitalTextbooks",
          },
        });
    router.push({
      path: "/bookdetail",
      query: {
        bookId: bookId,
      },
    });
  } else {
@@ -295,62 +258,21 @@
    if (parentData.parentProduct.length > 0) {
      bookId = parentData.parentProduct[parentData.parentProduct.length - 1].id;
    }
    console.log(bookId, "bookId");
    let crumbs = [
      {
        name,
        isCrumbs: true,
        type: "bookService",
        path: "/bookService/details",
      },
    ];
    // 在全局数据中设置面包屑
    crumbStore.setCrumbs({
      type: "bookService",
      data: crumbs,
      callback: (key: any) => {
        router.push({
          name: "bookDetails",
          query: {
            crumbsKey: key,
            bookId: bookId,
            bookName: name,
            type: "bookService",
          },
        });
    router.push({
      path: "/bookdetail",
      query: {
        bookId: bookId,
      },
    });
  }
};
//立即支付
const toPay = (orderNo) => {
  let crumbs: any[] = [
    {
      name: "我的订单", // 面包屑名称
      pathName: "myOrder", // 面包屑跳转路由,可传递 pathName 或 path
      isCrumbs: true, // 面包屑点击跳转时是否创建新的面包屑记录
      type: "personalCenter", // 如果需要创建新的面包屑记录,创建的type
      query: {
        type: "personalCenter",
      },
    },
  ];
  crumbs.push({
    name: "订单详情",
  });
  // 在全局数据中设置面包屑
  crumbStore.setCrumbs({
    type: "personalCenter",
    data: crumbs,
    callback: (key: any) => {
      router.push({
        path: "/paymentPage", //要跳转的页面
        query: {
          crumbsKey: key,
          orderNum: orderNo,
          type: "personalCenter",
        },
      });
  router.push({
    path: "/paymentPage", //要跳转的页面
    query: {
      orderNum: orderNo,
      type: "personalCenter",
    },
  });
};
src/views/personalCenter/userInfo.vue
@@ -298,7 +298,7 @@
import { useUserStore } from "@/store";
// import wxlogin from 'vue-wxlogin'
import teacherCertification from "./teacherCertification.vue";
// import login from '@/layout/components/login.vue'
import login from '@/layout/components/login.vue'
const userStore = useUserStore();
import { useRoute } from "vue-router";
import moment from "moment";