Browse Source

ai换装代码

shaogen1995 8 giờ trước cách đây
mục cha
commit
56ed6d01cc
68 tập tin đã thay đổi với 21845 bổ sung0 xóa
  1. 3 0
      AI换装/.browserslistrc
  2. 17 0
      AI换装/.eslintrc.js
  3. 23 0
      AI换装/.gitignore
  4. 24 0
      AI换装/README.md
  5. 5 0
      AI换装/babel.config.js
  6. 19 0
      AI换装/jsconfig.json
  7. 20415 0
      AI换装/package-lock.json
  8. 33 0
      AI换装/package.json
  9. BIN
      AI换装/public/favicon.ico
  10. 20 0
      AI换装/public/index.html
  11. BIN
      AI换装/public/staticData/ManPic/0.jpg
  12. BIN
      AI换装/public/staticData/ManPic/1.jpg
  13. BIN
      AI换装/public/staticData/ManPic/2.jpg
  14. BIN
      AI换装/public/staticData/ManPic/3.jpg
  15. BIN
      AI换装/public/staticData/ManPic/4.jpg
  16. BIN
      AI换装/public/staticData/ManPic/5.jpg
  17. BIN
      AI换装/public/staticData/ManPic/6.jpg
  18. BIN
      AI换装/public/staticData/ManPic/7.jpg
  19. BIN
      AI换装/public/staticData/WomanPic/10.jpg
  20. BIN
      AI换装/public/staticData/WomanPic/11.jpg
  21. BIN
      AI换装/public/staticData/WomanPic/12.jpg
  22. BIN
      AI换装/public/staticData/WomanPic/13.jpg
  23. BIN
      AI换装/public/staticData/WomanPic/14.jpg
  24. BIN
      AI换装/public/staticData/WomanPic/15.jpg
  25. BIN
      AI换装/public/staticData/WomanPic/16.jpg
  26. BIN
      AI换装/public/staticData/WomanPic/17.jpg
  27. BIN
      AI换装/public/staticData/WomanPic/8.jpg
  28. BIN
      AI换装/public/staticData/WomanPic/9.jpg
  29. 66 0
      AI换装/public/staticData/data.js
  30. 1 0
      AI换装/src/.env.development
  31. 1 0
      AI换装/src/.env.production
  32. 145 0
      AI换装/src/App.vue
  33. 22 0
      AI换装/src/api/home.js
  34. 10 0
      AI换装/src/assets/css/reset.css
  35. BIN
      AI换装/src/assets/fonts/SourceHanSansCN-Bold.otf
  36. BIN
      AI换装/src/assets/fonts/SourceHanSansCN-Regular.otf
  37. BIN
      AI换装/src/assets/img/BusyView/busyBg.png
  38. BIN
      AI换装/src/assets/img/BusyView/resetBtnBg.png
  39. BIN
      AI换装/src/assets/img/BusyView/time.png
  40. BIN
      AI换装/src/assets/img/BusyView/tip.png
  41. BIN
      AI换装/src/assets/img/CraftingView/AIText.png
  42. BIN
      AI换装/src/assets/img/CraftingView/boxBg.png
  43. BIN
      AI换装/src/assets/img/CraftingView/craftingBg.jpg
  44. BIN
      AI换装/src/assets/img/CraftingView/downloadBg.png
  45. BIN
      AI换装/src/assets/img/CraftingView/resetBg.png
  46. BIN
      AI换装/src/assets/img/CraftingView/sexLeftAc.png
  47. BIN
      AI换装/src/assets/img/CraftingView/sexRight.png
  48. BIN
      AI换装/src/assets/img/CraftingView/tipsBg.png
  49. BIN
      AI换装/src/assets/img/CraftingView/xiangyun.png
  50. BIN
      AI换装/src/assets/img/OvertimeView/time.png
  51. BIN
      AI换装/src/assets/img/OvertimeView/tip.png
  52. BIN
      AI换装/src/assets/img/close.png
  53. BIN
      AI换装/src/assets/img/landtip.png
  54. BIN
      AI换装/src/assets/img/loading.gif
  55. BIN
      AI换装/src/assets/logo.png
  56. 63 0
      AI换装/src/components/BusyView.vue
  57. 445 0
      AI换装/src/components/CraftingView.vue
  58. 75 0
      AI换装/src/components/OvertimeView.vue
  59. 7 0
      AI换装/src/components/socket.js
  60. 18 0
      AI换装/src/main.js
  61. 21 0
      AI换装/src/router/index.js
  62. 29 0
      AI换装/src/store/index.js
  63. 13 0
      AI换装/src/utils/auth.js
  64. 35 0
      AI换装/src/utils/browser.js
  65. 3 0
      AI换装/src/utils/https.js
  66. 165 0
      AI换装/src/utils/request.js
  67. 138 0
      AI换装/src/views/Home.vue
  68. 29 0
      AI换装/vue.config.js

+ 3 - 0
AI换装/.browserslistrc

@@ -0,0 +1,3 @@
+> 1%
+last 2 versions
+not dead

+ 17 - 0
AI换装/.eslintrc.js

@@ -0,0 +1,17 @@
+module.exports = {
+  root: true,
+  env: {
+    node: true
+  },
+  'extends': [
+    'plugin:vue/essential',
+    'eslint:recommended'
+  ],
+  parserOptions: {
+    parser: '@babel/eslint-parser'
+  },
+  rules: {
+    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
+  }
+}

+ 23 - 0
AI换装/.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 24 - 0
AI换装/README.md

@@ -0,0 +1,24 @@
+# hunqingwenhua
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 5 - 0
AI换装/babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

+ 19 - 0
AI换装/jsconfig.json

@@ -0,0 +1,19 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "module": "esnext",
+    "baseUrl": "./",
+    "moduleResolution": "node",
+    "paths": {
+      "@/*": [
+        "src/*"
+      ]
+    },
+    "lib": [
+      "esnext",
+      "dom",
+      "dom.iterable",
+      "scripthost"
+    ]
+  }
+}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 20415 - 0
AI换装/package-lock.json


+ 33 - 0
AI换装/package.json

@@ -0,0 +1,33 @@
+{
+  "name": "hunqingwenhua",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "axios": "^1.6.5",
+    "core-js": "^3.8.3",
+    "element-ui": "^2.15.14",
+    "normalize.css": "^8.0.1",
+    "vue": "^2.6.14",
+    "vue-router": "^3.5.1",
+    "vuex": "^3.6.2"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.12.16",
+    "@babel/eslint-parser": "^7.12.16",
+    "@vue/cli-plugin-babel": "~5.0.0",
+    "@vue/cli-plugin-eslint": "~5.0.0",
+    "@vue/cli-plugin-router": "~5.0.0",
+    "@vue/cli-plugin-vuex": "~5.0.0",
+    "@vue/cli-service": "~5.0.0",
+    "eslint": "^7.32.0",
+    "eslint-plugin-vue": "^8.0.3",
+    "less": "^4.0.0",
+    "less-loader": "^8.0.0",
+    "vue-template-compiler": "^2.6.14"
+  }
+}

BIN
AI换装/public/favicon.ico


+ 20 - 0
AI换装/public/index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="">
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width,initial-scale=1.0">
+  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+  <script src="./staticData/data.js"></script>
+  <title>AI试衣间</title>
+</head>
+
+<body>
+  <noscript>
+    <strong></strong>
+  </noscript>
+  <div id="app"></div>
+</body>
+
+</html>

BIN
AI换装/public/staticData/ManPic/0.jpg


BIN
AI换装/public/staticData/ManPic/1.jpg


BIN
AI换装/public/staticData/ManPic/2.jpg


BIN
AI换装/public/staticData/ManPic/3.jpg


BIN
AI换装/public/staticData/ManPic/4.jpg


BIN
AI换装/public/staticData/ManPic/5.jpg


BIN
AI换装/public/staticData/ManPic/6.jpg


BIN
AI换装/public/staticData/ManPic/7.jpg


BIN
AI换装/public/staticData/WomanPic/10.jpg


BIN
AI换装/public/staticData/WomanPic/11.jpg


BIN
AI换装/public/staticData/WomanPic/12.jpg


BIN
AI换装/public/staticData/WomanPic/13.jpg


BIN
AI换装/public/staticData/WomanPic/14.jpg


BIN
AI换装/public/staticData/WomanPic/15.jpg


BIN
AI换装/public/staticData/WomanPic/16.jpg


BIN
AI换装/public/staticData/WomanPic/17.jpg


BIN
AI换装/public/staticData/WomanPic/8.jpg


BIN
AI换装/public/staticData/WomanPic/9.jpg


+ 66 - 0
AI换装/public/staticData/data.js

@@ -0,0 +1,66 @@
+// const baseUrlTemp = "https://sit-wedding.4dage.com:8129";
+const baseUrlTemp = "192.168.20.62:8127";
+
+const dataAll = {
+  compoundPicList: {
+    manList: [
+      {
+        id: 0,
+      },
+      {
+        id: 1,
+      },
+      {
+        id: 2,
+      },
+      {
+        id: 3,
+      },
+      {
+        id: 4,
+      },
+      {
+        id: 5,
+      },
+      {
+        id: 6,
+      },
+      {
+        id: 7,
+      },
+    ],
+    womanList: [
+      {
+        id: 8,
+      },
+      {
+        id: 9,
+      },
+      {
+        id: 10,
+      },
+      {
+        id: 11,
+      },
+      {
+        id: 12,
+      },
+      {
+        id: 13,
+      },
+      {
+        id: 14,
+      },
+      {
+        id: 15,
+      },
+      {
+        id: 16,
+      },
+      {
+        id: 17,
+      },
+ 
+    ],
+  },
+};

+ 1 - 0
AI换装/src/.env.development

@@ -0,0 +1 @@
+VUE_APP_URL=

+ 1 - 0
AI换装/src/.env.production

@@ -0,0 +1 @@
+VUE_APP_URL=

+ 145 - 0
AI换装/src/App.vue

@@ -0,0 +1,145 @@
+<template>
+  <!-- <div id="app">
+    <nav>
+      <router-link to="/">Home</router-link> |
+      <router-link to="/about">About</router-link>
+      <div class="orientation-tip" v-if="isMobile"></div>
+      <div>
+        <img :src="require('@/assets/img/landtip.png')" alt="" />
+        <p>请在竖屏模式观看</p>
+      </div>
+    </nav>
+    <router-view />
+  </div> -->
+  <div class="vvvv" id="app">
+    <router-view />
+    <div class="orientation-tip" v-if="isMobile">
+      <div>
+        <img src='./assets/img/landtip.png' alt="" />
+        <p>请在竖屏模式观看</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import browser from '@/utils/browser'
+
+export default {
+  components: {},
+  data() {
+    return {
+      isMobile: browser.mobile,
+      time: null
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+
+  },
+  created() {
+
+    // console.log('dataAll数据', dataAll)
+
+    // 存入静态数据到仓库中
+    this.$store.dispatch('changeDataAll', dataAll);
+    const dom = document.querySelector("#app");
+    if (dom && document.documentElement.clientWidth < 480) {
+      dom.style.height = document.documentElement.clientHeight + "px";
+    }
+    // 移动端
+    window.addEventListener(
+      "resize",
+      () => {
+        //@ts-ignore
+        clearTimeout(this.time);
+        //@ts-ignore
+        this.time = window.setTimeout(() => {
+          // 根元素
+          const dom = document.querySelector("#app");
+          if (dom && document.documentElement.clientWidth < 480) {
+            dom.style.height = document.documentElement.clientHeight + "px";
+          }
+        }, 100);
+      },
+      true
+    );
+  },
+  mounted() {
+
+  },
+  beforeCreate() { }, //生命周期 - 创建之前
+  beforeMount() { }, //生命周期 - 挂载之前
+  beforeUpdate() { }, //生命周期 - 更新之前
+  updated() { }, //生命周期 - 更新之后
+  beforeDestroy() { }, //生命周期 - 销毁之前
+  destroyed() { }, //生命周期 - 销毁完成
+  activated() { }, //如果页面有keep-alive缓存功能,这个函数会触发
+}
+</script>
+
+<style lang="less">
+@font-face {
+  font-family: 'SourceHanSansCN-Regular';
+  src: url('./assets/fonts/SourceHanSansCN-Regular.otf');
+}
+
+@font-face {
+  font-family: 'SourceHanSansCN-Bold';
+  src: url('./assets/fonts/SourceHanSansCN-Bold.otf');
+}
+
+#app {
+  height: 100%;
+  max-width: 500px;
+  height: 100%;
+  margin: 0 auto;
+}
+
+// 横屏体验
+.orientation-tip {
+  width: 100%;
+  height: 100%;
+  z-index: 10000;
+  position: fixed;
+  top: 0;
+  left: 0;
+  display: none;
+  background-color: rgba(0, 0, 0, 0.8);
+  color: #fff;
+
+  >div {
+    position: absolute;
+    top: 50%;
+    width: 100%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    text-align: center;
+
+    >img {
+      width: 20%;
+    }
+
+    >p {
+      font-size: 16px;
+      margin-top: 20px;
+      width: 100%;
+    }
+  }
+}
+
+/*竖屏*/
+@media screen and (orientation: portrait) {
+  .orientation-tip {
+    display: none;
+  }
+}
+
+/*横屏*/
+@media screen and (orientation: landscape) {
+  .orientation-tip {
+    display: block;
+  }
+}
+</style>

+ 22 - 0
AI换装/src/api/home.js

@@ -0,0 +1,22 @@
+import request from "@/utils/request";
+
+export function getInfo(params) {
+  return request({
+    url: "/user/info",
+    method: "get",
+    params,
+  });
+}
+
+
+//返回所有的res信息
+export function login(data) {
+  return request({
+    url: "/user/login",
+    method: "post",
+    data,
+    meta: {
+      responseAll: true, // 返回所有的信息,包括状态码和message和data
+    },
+  });
+}

+ 10 - 0
AI换装/src/assets/css/reset.css

@@ -0,0 +1,10 @@
+* {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  box-sizing: border-box;
+}
+html,
+body {
+  height: 100%;
+}

BIN
AI换装/src/assets/fonts/SourceHanSansCN-Bold.otf


BIN
AI换装/src/assets/fonts/SourceHanSansCN-Regular.otf


BIN
AI换装/src/assets/img/BusyView/busyBg.png


BIN
AI换装/src/assets/img/BusyView/resetBtnBg.png


BIN
AI换装/src/assets/img/BusyView/time.png


BIN
AI换装/src/assets/img/BusyView/tip.png


BIN
AI换装/src/assets/img/CraftingView/AIText.png


BIN
AI换装/src/assets/img/CraftingView/boxBg.png


BIN
AI换装/src/assets/img/CraftingView/craftingBg.jpg


BIN
AI换装/src/assets/img/CraftingView/downloadBg.png


BIN
AI换装/src/assets/img/CraftingView/resetBg.png


BIN
AI换装/src/assets/img/CraftingView/sexLeftAc.png


BIN
AI换装/src/assets/img/CraftingView/sexRight.png


BIN
AI换装/src/assets/img/CraftingView/tipsBg.png


BIN
AI换装/src/assets/img/CraftingView/xiangyun.png


BIN
AI换装/src/assets/img/OvertimeView/time.png


BIN
AI换装/src/assets/img/OvertimeView/tip.png


BIN
AI换装/src/assets/img/close.png


BIN
AI换装/src/assets/img/landtip.png


BIN
AI换装/src/assets/img/loading.gif


BIN
AI换装/src/assets/logo.png


+ 63 - 0
AI换装/src/components/BusyView.vue

@@ -0,0 +1,63 @@
+<template>
+  <div class="crafting">
+    <div class="content">
+      <img src="../assets/img/loading.gif" alt="" />
+      <p>有用户正在体验中</p>
+      <p>待用户退出后,会为您自动连接</p>
+      <p>请耐心等待</p>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  data() {
+    return {};
+  },
+  computed: {},
+  watch: {},
+  methods: {},
+  created() {},
+  mounted() {},
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang="less" scoped>
+.crafting {
+  width: 100%;
+  height: 100%;
+  max-width: 500px;
+  background: url(@/assets/img/CraftingView/craftingBg.jpg);
+  background-size: cover;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  position: relative;
+  .content {
+    width: 85%;
+    height: 65%;
+    background: url(@/assets/img/BusyView/busyBg.png);
+    background-size: 100% 100%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    margin-left: -10%;
+    margin-top: -10%;
+    padding-left: 10%;
+    color: #fff;
+    font-size: 14px;
+    & > p {
+      margin-top: 10px;
+    }
+  }
+}
+</style>

+ 445 - 0
AI换装/src/components/CraftingView.vue

@@ -0,0 +1,445 @@
+<template>
+  <div class="crafting">
+    <!-- <img class="xiangyun" src="@/assets/img/CraftingView/xiangyun.png" alt="" /> -->
+    <div class="content">
+      <div class="content-top">
+        <img
+          class="ai-text"
+          src="@/assets/img/CraftingView/AIText.png"
+          alt=""
+        />
+        <div :class="`content-sex contentAc${curSex}`">
+          <div
+            class="boy"
+            v-for="item in topArr"
+            :key="item.id"
+            @click="curSexFu(item)"
+          >
+            {{ item.name }}
+          </div>
+        </div>
+      </div>
+      <div class="content-center">
+        <div class="box">
+          <div class="box-content">
+            <div
+              class="box-item"
+              v-for="item in curSexList"
+              :key="item.id"
+              @click="imgClick(item.id)"
+            >
+              <img
+                :src="`${baseStateUrl}/${
+                  curSex === 1 ? 'ManPic' : 'WomanPic'
+                }/${item.id}.jpg`"
+                alt=""
+              />
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="content-bottom">
+        <div class="tips">
+          如{{ countDownNumber45 }}秒内未作操作,将自动退出
+        </div>
+        <div class="bottom-btns">
+          <div
+            class="download"
+            @click="downImg"
+            v-show="craftingUrl && isLoding === 0"
+          >
+            查看图片
+          </div>
+          <div
+            class="resetbtn"
+            :class="{ resetbtnOne: !(craftingUrl && isLoding === 0) }"
+            @click="againFu"
+          >
+            重新拍摄
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 查看图片 -->
+    <div class="lookImg" :class="{ lookImgAc: lookImgFlag }" v-if="craftingUrl">
+      <img :src="craftingUrl" alt="" />
+      <div
+        class="close"
+        @click="(countDownNumber45 = 45), (lookImgFlag = false)"
+      >
+        <img src="../assets/img/close.png" alt="" />
+      </div>
+
+      <div class="lookTit">
+        如{{ countDownNumber45 }}秒内未作操作,将自动退出
+        <br />
+        长按保存图片
+      </div>
+    </div>
+
+    <!-- 加载中 -->
+    <div class="isLodingBox" v-show="isLoding === 1">
+      <div><img src="../assets/img/loading.gif" alt="" /></div>
+    </div>
+  </div>
+</template>
+
+<script>
+import baseUrl from "@/utils/https.js";
+export default {
+  components: {},
+  props: ["craftingUrl", "isLoding"],
+  data() {
+    return {
+      curSex: 1,
+      baseStateUrl: baseUrl,
+      // 3分钟计时
+      timer: null,
+      // 45s计时间
+      timer2: null,
+      countDownNumber45: 45,
+
+      topArr: [
+        { id: 1, name: "男", type: "man" },
+        { id: 2, name: "女", type: "woman" },
+      ],
+
+      // 查看图片
+      lookImgFlag: true,
+    };
+  },
+  computed: {
+    curSexList: function () {
+      // console.log(this.$store.state.dataAll.compoundPicList.manList);
+      return this.curSex == 1
+        ? this.$store.state.dataAll.compoundPicList.manList
+        : this.$store.state.dataAll.compoundPicList.womanList;
+    },
+  },
+  watch: {},
+  methods: {
+    sonImgShow() {
+      this.lookImgFlag = true;
+    },
+
+    // 点击 男 女
+    curSexFu(item) {
+      this.countDownNumber45 = 45;
+
+      if (this.curSex === item.id) return;
+
+      this.curSex = item.id;
+      this.$emit("sonMsg", { type: "WebChangeGender", data: item.type });
+    },
+
+    // 点击图片
+    imgClick(ind) {
+      this.countDownNumber45 = 45;
+      if (this.isLoding === 1) {
+        alert("照片合成中,请稍后操作");
+      } else {
+        this.$emit("sonMsg", { type: "WebChooseImageID", data: ind });
+      }
+    },
+
+    // 点击查看图片
+    downImg() {
+      this.countDownNumber45 = 45;
+      if (this.isLoding === 1) alert("照片合成中,请稍后操作");
+      else {
+        if (this.craftingUrl) this.lookImgFlag = true;
+        else alert("请先完成拍照");
+      }
+    },
+
+    // 点击重新拍摄
+    againFu() {
+      this.countDownNumber45 = 45;
+      this.$emit("sonMsg", { type: "WebReShoot", data: "" });
+    },
+  },
+  created() {
+    // console.log("绑定数据", this.baseStateUrl);
+    // 3分钟后,强制退出应用
+    this.timer = setInterval(() => {
+      // 强制退出应用
+      this.$emit("changeStateFu", "overtime");
+    }, 180000);
+
+    // 45s 持续递减
+    this.timer2 = setInterval(() => {
+      if (this.countDownNumber45 > 0) {
+        this.countDownNumber45--;
+      } else {
+        // 强制退出应用
+        this.$emit("changeStateFu", "overtime");
+      }
+    }, 1000);
+  },
+  mounted() {},
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {
+    clearInterval(this.timer);
+    clearInterval(this.timer2);
+  }, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang="less" scoped>
+.crafting {
+  width: 100%;
+  height: 100%;
+  background: url(@/assets/img/CraftingView/craftingBg.jpg);
+  background-size: cover;
+  position: relative;
+
+  .lookImg {
+    opacity: 0;
+    pointer-events: none;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 100;
+    width: 100%;
+    height: 100%;
+    transition: all 0.3s;
+    background-color: rgba(0, 0, 0, 0.6);
+    display: flex;
+    img {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      max-width: 100%;
+      max-height: 100%;
+    }
+    .lookTit {
+      pointer-events: none;
+      position: absolute;
+      z-index: 1;
+      bottom: 20px;
+      left: 0;
+      width: 100%;
+      text-align: center;
+      color: #fff;
+      font-size: 12px;
+      text-shadow: 1px 1px 1px red;
+    }
+    .close {
+      position: absolute;
+      top: 20px;
+      right: 20px;
+      z-index: 1;
+      width: 40px;
+      height: 40px;
+      border-radius: 50%;
+      background-color: rgba(0, 0, 0, 0.6);
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+  }
+  .lookImgAc {
+    opacity: 1;
+    pointer-events: auto;
+  }
+
+  .isLodingBox {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 99;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    & > div {
+      width: 100px;
+      height: 100px;
+      background-color: rgba(0, 0, 0, 0.8);
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      border-radius: 10px;
+    }
+  }
+
+  .xiangyun {
+    width: 160px;
+    position: absolute;
+    left: 50%;
+    transform: translateX(-110%);
+    /* left: 8vw; */
+    top: 5vh;
+  }
+
+  .content {
+    width: 100%;
+    height: 100%;
+    max-width: 500px;
+    position: absolute;
+    z-index: 2;
+    padding: 11% 0;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: space-between;
+
+    .content-top {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: space-between;
+      height: 15%;
+      // background: rgba(0, 0, 0, 0.548);
+
+      .ai-text {
+        width: 50%;
+      }
+
+      .content-sex {
+        width: 35%;
+        height: 4vh;
+        font-family: "SourceHanSansCN-Regular";
+        font-size: 1.3em;
+        display: flex;
+        margin-top: 10px;
+        margin-bottom: 20px;
+
+        .boy {
+          width: 50%;
+          height: 100%;
+          color: #ffffffa6;
+          margin-right: 2px;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          background-image: url("../assets/img/CraftingView/sexRight.png");
+          background-size: 100% 100%;
+          &:nth-of-type(2) {
+            margin-right: 0;
+            background-image: url("../assets/img/CraftingView/sexRight.png");
+          }
+        }
+      }
+      .contentAc1 {
+        .boy {
+          background-image: url("../assets/img/CraftingView/sexLeftAc.png");
+        }
+      }
+      .contentAc2 {
+        .boy {
+          &:nth-of-type(2) {
+            background-image: url("../assets/img/CraftingView/sexLeftAc.png");
+          }
+        }
+      }
+    }
+
+    .content-center {
+      width: 100%;
+      height: calc(100% - 22%);
+      // background: black;
+      display: flex;
+      justify-content: center;
+
+      .box {
+        width: 95%;
+        height: 100%;
+        background: url(@/assets/img/CraftingView/boxBg.png);
+        background-size: 100% 100%;
+        padding: 10% 8%;
+
+        ::-webkit-scrollbar {
+          display: none;
+          /* 隐藏滚动条 */
+        }
+
+        .box-content {
+          width: 100%;
+          height: 100%;
+          overflow: auto;
+          display: grid;
+          grid-template-columns: 1fr 1fr 1fr;
+          // align-content: space-around;
+          grid-gap: 10px;
+        }
+
+        img {
+          width: 100%;
+          height: 100%;
+          // object-fit: contain;
+          border-radius: 10px;
+          border: yellow 1px solid;
+        }
+      }
+    }
+
+    .content-bottom {
+      width: 100%;
+      height: 15%;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      padding: 10px auto 30px auto;
+
+      .tips {
+        // font-family: 'SourceHanSansCN-Bold';
+        font-size: 0.6em;
+        color: white;
+        width: 80%;
+        height: 30px;
+        text-align: center;
+        line-height: 30px;
+        background: url(@/assets/img/CraftingView/tipsBg.png);
+        background-size: 100% 100%;
+      }
+
+      .bottom-btns {
+        display: flex;
+        justify-content: center;
+        font-family: "SourceHanSansCN-Bold";
+        font-size: 0.9em;
+        color: #ffffff;
+        letter-spacing: 2px;
+        width: 80%;
+
+        .download {
+          width: 40vw;
+          height: 45px;
+          background: url(@/assets/img/CraftingView/downloadBg.png);
+          background-size: 100% 100%;
+          margin-right: 2px;
+          padding-right: 6%;
+          box-sizing: border-box;
+          display: flex;
+          justify-content: right;
+          align-items: center;
+        }
+
+        .resetbtn {
+          width: 40vw;
+          height: 45px;
+          background: url(@/assets/img/CraftingView/resetBg.png);
+          background-size: 100% 100%;
+          margin-left: 2px;
+          padding-left: 6%;
+          box-sizing: border-box;
+          display: flex;
+          justify-content: left;
+          align-items: center;
+        }
+        .resetbtnOne {
+          padding-left: 12%;
+        }
+      }
+    }
+  }
+}
+</style>

+ 75 - 0
AI换装/src/components/OvertimeView.vue

@@ -0,0 +1,75 @@
+<template>
+  <div class="crafting">
+    <div class="content">
+      <img class="time" src="@/assets/img/OvertimeView/time.png" alt="" />
+      <img class="tip" src="@/assets/img/OvertimeView/tip.png" alt="" />
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  data() {
+    return {};
+  },
+  computed: {},
+  watch: {},
+  methods: {},
+  created() {},
+  mounted() {},
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang="less" scoped>
+.crafting {
+  width: 100%;
+  height: 100%;
+  max-width: 500px;
+  background: url(@/assets/img/CraftingView/craftingBg.jpg);
+  background-size: cover;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+
+  .content {
+    width: 85%;
+    height: 65%;
+    background: url(@/assets/img/BusyView/busyBg.png);
+    background-size: 100% 100%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    margin-left: -10%;
+    padding-left: 10%;
+    margin-top: -10%;
+
+    .time {
+      width: 10%;
+    }
+
+    .tip {
+      width: 50%;
+    }
+  }
+
+  .resetBtn {
+    width: 70%;
+    height: 40px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background: url(@/assets/img/BusyView/resetBtnBg.png);
+    background-size: 100% 100%;
+    margin-top: 20px;
+  }
+}
+</style>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 7 - 0
AI换装/src/components/socket.js


+ 18 - 0
AI换装/src/main.js

@@ -0,0 +1,18 @@
+import Vue from 'vue'
+import App from './App.vue'
+import router from './router'
+import store from './store'
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import 'normalize.css/normalize.css'
+import './assets/css/reset.css'
+
+Vue.use(ElementUI)
+
+Vue.config.productionTip = false
+
+new Vue({
+  router,
+  store,
+  render: h => h(App)
+}).$mount('#app')

+ 21 - 0
AI换装/src/router/index.js

@@ -0,0 +1,21 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+
+Vue.use(VueRouter)
+
+const routes = [
+  {
+    path:'/',
+    name: 'home',
+    component: () => import( '../views/Home.vue')
+  },
+
+]
+
+const router = new VueRouter({
+  // mode: 'history',
+  base: process.env.BASE_URL,
+  routes
+})
+
+export default router

+ 29 - 0
AI换装/src/store/index.js

@@ -0,0 +1,29 @@
+import Vue from 'vue'
+// 引入 vuex
+import Vuex from 'vuex'
+Vue.use(Vuex)
+
+
+// 准备actions,用于响应组件中的动作
+const actions = {
+  changeDataAll(context, value) {
+    context.commit('changeCommitDataAll', value)
+  }
+}
+// mutations 用于操作数据(state)
+const mutations = {
+  changeCommitDataAll(state, value) {
+    state.dataAll = value
+  }
+}
+// state 用于存储数据
+const state = {
+  dataAll: {}
+}
+
+
+export default new Vuex.Store({
+  actions,
+  mutations,
+  state
+})

+ 13 - 0
AI换装/src/utils/auth.js

@@ -0,0 +1,13 @@
+function getLocal(key = "token") {
+  return localStorage.getItem(key);
+}
+// 删除
+function removeLocal(key = "token") {
+  window.localStorage.removeItem(key);
+}
+// 保存
+function setLocal(value, key = "token") {
+  window.localStorage.setItem(key, value);
+}
+export { getLocal, removeLocal, setLocal };
+

+ 35 - 0
AI换装/src/utils/browser.js

@@ -0,0 +1,35 @@
+function versions () {
+  var u = window.navigator.userAgent
+  return {
+    // IE内核
+    trident: u.indexOf('Trident') > -1,
+    // Firefox
+    firefox: u.indexOf('Firefox') > -1,
+    // edge
+    edge: u.indexOf('Edge') > -1,
+    // opera内核
+    presto: u.indexOf('Presto') > -1,
+    // 苹果、谷歌内核
+    webKit: u.indexOf('AppleWebKit') > -1,
+    // 火狐内核
+    gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') === -1,
+    // 是否为移动终端
+    mobile: /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent),
+    // ios终端
+    ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
+    // android终端或者uc浏览器
+    android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1,
+    // 是否为iPhone或者安卓QQ浏览器
+    iPhone: u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1,
+    // 是否为iPad
+    iPad: u.indexOf('iPad') > -1,
+    // 是否为web应用程序,没有头部与底部
+    webApp: u.indexOf('Safari') === -1,
+    // 是否为微信浏览器
+    weixin: ~u.indexOf('MicroMessenger'),
+    // 获取浏览器语言
+    language: (navigator.browserLanguage || navigator.language).toLowerCase()
+  }
+}
+
+export default versions()

+ 3 - 0
AI换装/src/utils/https.js

@@ -0,0 +1,3 @@
+const baseUrl = './staticData'
+
+export default baseUrl

+ 165 - 0
AI换装/src/utils/request.js

@@ -0,0 +1,165 @@
+import axios from 'axios'
+import { Message, Loading, MessageBox } from 'element-ui'
+import store from '@/store'
+import { getLocal } from '@/utils/auth'
+
+// 创建axios实例
+const service = axios.create({
+  baseURL: process.env.VUE_APP_URL, // api的base_url
+  timeout: 5000 // 请求超时时间
+})
+
+// request拦截器
+service.interceptors.request.use(
+  config => {
+    removePending(config)
+    // 如果repeatRequest不配置,那么默认该请求就取消重复接口请求
+    !config.repeatRequest && addPending(config)
+    // 打开loading
+    if (config.loading) {
+      LoadingInstance._count++
+      if (LoadingInstance._count === 1) {
+        openLoading(config.loadingDom)
+      }
+    }
+    // 如果登录了,有token,则请求携带token
+    // Do something before request is sent
+    if (store.state.user.token) {
+      config.headers['X-Token'] = getLocal('token') // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
+    }
+    return config
+  },
+  error => {
+    // Do something with request error
+    console.log(error) // for debug
+    Promise.reject(error)
+  }
+)
+
+// respone拦截器
+service.interceptors.response.use(
+  // response => response,
+  /**
+   * 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
+   * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
+   */
+  response => {
+    // 已完成请求的删除请求中数组
+    removePending(response.config)
+    // 关闭loading
+    if (response.config.loading) {
+      closeLoading()
+    }
+
+    const res = response.data
+    // 处理异常的情况
+    if (res.code !== 200) {
+      Message({
+        message: res.message,
+        type: 'error',
+        duration: 5 * 1000
+      })
+      // 403:非法的token; 50012:其他客户端登录了;  401:Token 过期了;
+      if (res.code === 403 || res.code === 50012 || res.code === 401) {
+        MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
+          confirmButtonText: '重新登录',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          store.dispatch('user/FedLogOut').then(() => {
+            location.reload() // 为了重新实例化vue-router对象 避免bug
+          })
+        })
+      }
+      return Promise.reject(new Error('error'))
+    } else {
+      // 默认只返回data,不返回状态码和message
+      // 通过 meta 中的 responseAll 配置来取决后台是否返回所有数据(包括状态码,message和data)
+      const isbackAll = response.config.meta && response.config.meta.responseAll
+      if (isbackAll) {
+        return res
+      } else {
+        return res.data
+      }
+    }
+  },
+  error => {
+    error.config && removePending(error.config)
+    // 关闭loading
+    if (error.config.loading) {
+      closeLoading()
+    }
+    console.log('err' + error) // for debug
+    Message({
+      message: error.message,
+      type: 'error',
+      duration: 5 * 1000
+    })
+    return Promise.reject(error)
+  }
+)
+
+// --------------------------------取消接口重复请求的函数-----------------------------------
+// axios.js
+const pendingMap = new Map()
+/**
+ * 生成每个请求唯一的键
+ * @param {*} config
+ * @returns string
+ */
+function getPendingKey(config) {
+  let { url, method, params, data } = config
+  if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象
+  return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&')
+}
+
+/**
+ * 储存每个请求唯一值, 也就是cancel()方法, 用于取消请求
+ * @param {*} config
+ */
+function addPending(config) {
+  const pendingKey = getPendingKey(config)
+  config.cancelToken =
+    config.cancelToken ||
+    new axios.CancelToken(cancel => {
+      if (!pendingMap.has(pendingKey)) {
+        pendingMap.set(pendingKey, cancel)
+      }
+    })
+}
+/**
+ * 删除重复的请求
+ * @param {*} config
+ */
+function removePending(config) {
+  const pendingKey = getPendingKey(config)
+  if (pendingMap.has(pendingKey)) {
+    const cancelToken = pendingMap.get(pendingKey)
+    cancelToken(pendingKey)
+    pendingMap.delete(pendingKey)
+  }
+}
+// ----------------------------------loading的函数-------------------------------
+const LoadingInstance = {
+  _target: null, // 保存Loading实例
+  _count: 0
+}
+function openLoading(loadingDom) {
+  LoadingInstance._target = Loading.service({
+    lock: true,
+    text: '数据正在加载中',
+    spinner: 'el-icon-loading',
+    background: 'rgba(25, 32, 53, 1)',
+    target: loadingDom || 'body'
+  })
+}
+function closeLoading() {
+  if (LoadingInstance._count > 0) LoadingInstance._count--
+  if (LoadingInstance._count === 0) {
+    LoadingInstance._target.close()
+    LoadingInstance._target = null
+  }
+}
+
+export default service
+

+ 138 - 0
AI换装/src/views/Home.vue

@@ -0,0 +1,138 @@
+<template>
+  <div class="all">
+    <!-- 忙线页面 -->
+    <Busy v-if="state == 'busy'" @sonMsg="sonMsg" />
+    <!-- ai合成页面 -->
+    <Crafting
+      ref="CraftingRef"
+      v-if="state == 'crafting'"
+      @sonMsg="sonMsg"
+      :craftingUrl="craftingUrl"
+      :isLoding="isLoding"
+      @changeStateFu="changeStateFu"
+    />
+    <!-- 超时页面 -->
+    <Overtime v-if="state == 'overtime'" />
+
+    <!-- 异常页面 -->
+    <div class="errBox" v-if="state === ''">
+      <span v-show="errShow">服务端异常,请联系管理员</span>
+    </div>
+  </div>
+</template>
+
+<script>
+
+import { io } from "../components/socket";
+
+import Crafting from "@/components/CraftingView.vue";
+import Busy from "@/components/BusyView.vue";
+import Overtime from "@/components/OvertimeView.vue";
+
+export default {
+  components: { Crafting, Busy, Overtime },
+  data() {
+    return {
+      // busy---忙线页,crafting -- 合成页, overtime -- 过时页
+      state: "",
+      socket: null,
+      errShow: false,
+      // 合成页的数据
+      craftingUrl: "",
+      isLoding: 0,
+    };
+  },
+  computed: {},
+  watch: {
+    state(val) {
+      if (val === "overtime") {
+        // 通知服务端关闭
+        this.socket.emit("CloseConnect");
+        // 断开连接
+        this.socket.close();
+      }
+    },
+  },
+  methods: {
+    // 给 合成页调用
+    changeStateFu(newState) {
+      // this.state = newState;
+    },
+
+    // 合成页面 控制
+    sonMsg(info) {
+      console.log("主动调用", info);
+      this.socket.emit(info.type, info.data);
+    },
+  },
+  created() {    
+    this.socket = io(baseUrlTemp, { transports: ["websocket", "polling"] });
+
+    setTimeout(() => {
+      console.log("---------id:", this.socket.id);
+      this.errShow = true;
+    }, 500);
+  },
+  mounted() {
+    // 监听 是否 有别人使用
+    this.socket.on("WebIsActive", (data) => {
+      console.log("是否有人正在使用:", data);
+
+      // 1进入 crafting -- 合成页
+      // 0进入 busy---忙线页
+      this.state = data === 1 ? "crafting" : "busy";
+    });
+
+    // 监听 图片地址 是否返回
+    this.socket.on("WebMergeURL", (data) => {
+      console.log("图片地址返回:", data);
+      if (data) this.craftingUrl = data;
+    });
+
+    // 监听 当前是否在loading(正在进行图片合成操作) 1 为 正在loading , 0 为 不在loading
+    this.socket.on("WebIsOperation", (data) => {
+      if (data === 1) this.craftingUrl = "";
+
+      if (this.isLoding === 0 && data === 0) this.craftingUrl = "";
+
+      console.log("照片合成状态", data);
+      this.isLoding = data;
+
+      if (data === 0 && this.craftingUrl) {
+        this.$refs.CraftingRef.sonImgShow();
+      }
+    });
+
+    // 连接异常时,会触发
+    this.socket.on("connect_error", (err) => {
+      console.log(err);
+      // 如果连接异常,修改transports传输方式
+      this.socket.io.opts.transports = ["polling", "websocket"];
+    });
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang="less" scoped>
+.all {
+  width: 100%;
+  height: 100%;
+  .errBox {
+    width: 100%;
+    height: 100%;
+    background: url(@/assets/img/CraftingView/craftingBg.jpg);
+    background-size: cover;
+    position: relative;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    color: #fff;
+  }
+}
+</style>

+ 29 - 0
AI换装/vue.config.js

@@ -0,0 +1,29 @@
+const path = require('path')
+function resolve(dir) { // 配置别名
+  return path.join(__dirname, dir)
+}
+const { defineConfig } = require('@vue/cli-service')
+module.exports = defineConfig({
+  publicPath: './',
+  transpileDependencies: true,
+  lintOnSave: false,
+  configureWebpack: {
+    resolve: {
+      alias: {
+        '@': resolve('src')
+      }
+    }
+  },
+  devServer: {
+    //开启代理服务器 (方式1)   配置多个代理
+    proxy: {
+      "/api": {
+        //'/api'是自行设置的请求前缀
+        target: "http://localhost:5000",
+        // ws: true,//用于支持websocket
+        changeOrigin: true, //用于控制请求头中的host值
+        pathRewrite: { "^/api": "" }, //路径重写,(正则)匹配以api开头的路径为空(将请求前缀删除)
+      },
+    },
+  }
+})