From b77e36a178f28a810aac6d481c30c0a3aee95d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BC=96=E7=A0=81=E7=8C=BF?= Date: Tue, 7 Oct 2025 03:17:55 +0800 Subject: [PATCH] first commit --- .dockerignore | 14 + .env.development | 26 + .env.production | 23 + .gitea/workflows/build.yml | 75 + Dockerfile | 22 + README.md | 156 + act-runner.yml | 17 + app-product.yml | 39 + dist/assets/ProductDetail-C2SXoWRu.js | 1 + dist/assets/ProductDetail-rjscZczN.css | 1 + dist/assets/ProductList-BnGJM5LT.js | 1 + dist/assets/ProductList-CV-Muv1j.css | 1 + ...ederation_expose_ProductDomain-J98eKK33.js | 1 + ...ederation_expose_ProductRouter-BB_8fJdP.js | 2 + .../assets/__federation_fn_import-E6wRZccp.js | 1 + dist/assets/index-KMVTlfvo.js | 1 + dist/assets/productModule-C57DerbR.js | 1 + dist/assets/remoteEntry.js | 1 + dist/index.html | 17 + dist/stats.html | 4949 +++++++++++++++++ docker-compose.yml | 13 + index.html | 16 + nginx.conf | 14 + node_modules/.bin/browserslist | 21 + node_modules/.bin/lessc | 21 + node_modules/.bin/npm-run-all | 21 + node_modules/.bin/npm-run-all2 | 21 + node_modules/.bin/rollup | 21 + node_modules/.bin/rollup-plugin-visualizer | 21 + node_modules/.bin/run-p | 21 + node_modules/.bin/run-s | 21 + node_modules/.bin/tsc | 21 + node_modules/.bin/tsserver | 21 + node_modules/.bin/vite | 21 + node_modules/.bin/vue-tsc | 21 + node_modules/@element-plus/icons-vue | 1 + node_modules/@tsconfig/node22 | 1 + node_modules/@types/node | 1 + node_modules/@vitejs/plugin-vue | 1 + node_modules/@vitejs/plugin-vue-jsx | 1 + node_modules/@vue/tsconfig | 1 + node_modules/element-plus | 1 + node_modules/less | 1 + node_modules/npm-run-all2 | 1 + node_modules/pinia | 1 + node_modules/rollup-plugin-visualizer | 1 + node_modules/typescript | 1 + node_modules/vite | 1 + node_modules/vite-federation | 1 + node_modules/vite-plugin-nacos | 1 + node_modules/vite-plugin-vue-devtools | 1 + node_modules/vue | 1 + node_modules/vue-router | 1 + node_modules/vue-tsc | 1 + package.json | 39 + src/App.tsx | 27 + .../services/ProductApplicationService.ts | 22 + src/domains/product/di/productModule.ts | 38 + .../product/domain/entities/Product.ts | 141 + .../product/domain/enums/ErrorEnums.ts | 7 + src/domains/product/domain/events/README.md | 1 + .../product/domain/type/ProductType.ts | 9 + .../product/domain/value-objects/README.md | 1 + src/domains/product/index.ts | 6 + .../product/infr/api/HttpProductRepository.ts | 27 + src/domains/product/infr/config/HttpConfig.ts | 11 + .../ports/repositories/ProductRepository.ts | 20 + src/features/product/assets/README.md | 1 + src/features/product/components/README.md | 1 + src/features/product/composables/README.md | 1 + src/features/product/index.ts | 0 src/features/product/router/index.ts | 16 + .../ProductDetail/ProductDetail.module.less | 5 + .../views/ProductDetail/ProductDetail.tsx | 62 + .../views/ProductList/ProductList.module.less | 5 + .../product/views/ProductList/ProductList.tsx | 79 + src/main.ts | 12 + src/shared/types/env.d.ts | 4 + src/shared/types/shared.d.ts | 29 + tsconfig.app.json | 33 + tsconfig.json | 11 + tsconfig.node.json | 19 + vite.config.ts | 66 + 83 files changed, 6356 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.development create mode 100644 .env.production create mode 100644 .gitea/workflows/build.yml create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 act-runner.yml create mode 100644 app-product.yml create mode 100644 dist/assets/ProductDetail-C2SXoWRu.js create mode 100644 dist/assets/ProductDetail-rjscZczN.css create mode 100644 dist/assets/ProductList-BnGJM5LT.js create mode 100644 dist/assets/ProductList-CV-Muv1j.css create mode 100644 dist/assets/__federation_expose_ProductDomain-J98eKK33.js create mode 100644 dist/assets/__federation_expose_ProductRouter-BB_8fJdP.js create mode 100644 dist/assets/__federation_fn_import-E6wRZccp.js create mode 100644 dist/assets/index-KMVTlfvo.js create mode 100644 dist/assets/productModule-C57DerbR.js create mode 100644 dist/assets/remoteEntry.js create mode 100644 dist/index.html create mode 100644 dist/stats.html create mode 100644 docker-compose.yml create mode 100644 index.html create mode 100644 nginx.conf create mode 100755 node_modules/.bin/browserslist create mode 100755 node_modules/.bin/lessc create mode 100755 node_modules/.bin/npm-run-all create mode 100755 node_modules/.bin/npm-run-all2 create mode 100755 node_modules/.bin/rollup create mode 100755 node_modules/.bin/rollup-plugin-visualizer create mode 100755 node_modules/.bin/run-p create mode 100755 node_modules/.bin/run-s create mode 100755 node_modules/.bin/tsc create mode 100755 node_modules/.bin/tsserver create mode 100755 node_modules/.bin/vite create mode 100755 node_modules/.bin/vue-tsc create mode 120000 node_modules/@element-plus/icons-vue create mode 120000 node_modules/@tsconfig/node22 create mode 120000 node_modules/@types/node create mode 120000 node_modules/@vitejs/plugin-vue create mode 120000 node_modules/@vitejs/plugin-vue-jsx create mode 120000 node_modules/@vue/tsconfig create mode 120000 node_modules/element-plus create mode 120000 node_modules/less create mode 120000 node_modules/npm-run-all2 create mode 120000 node_modules/pinia create mode 120000 node_modules/rollup-plugin-visualizer create mode 120000 node_modules/typescript create mode 120000 node_modules/vite create mode 120000 node_modules/vite-federation create mode 120000 node_modules/vite-plugin-nacos create mode 120000 node_modules/vite-plugin-vue-devtools create mode 120000 node_modules/vue create mode 120000 node_modules/vue-router create mode 120000 node_modules/vue-tsc create mode 100644 package.json create mode 100644 src/App.tsx create mode 100644 src/domains/product/application/services/ProductApplicationService.ts create mode 100644 src/domains/product/di/productModule.ts create mode 100644 src/domains/product/domain/entities/Product.ts create mode 100644 src/domains/product/domain/enums/ErrorEnums.ts create mode 100644 src/domains/product/domain/events/README.md create mode 100644 src/domains/product/domain/type/ProductType.ts create mode 100644 src/domains/product/domain/value-objects/README.md create mode 100644 src/domains/product/index.ts create mode 100644 src/domains/product/infr/api/HttpProductRepository.ts create mode 100644 src/domains/product/infr/config/HttpConfig.ts create mode 100644 src/domains/product/ports/repositories/ProductRepository.ts create mode 100644 src/features/product/assets/README.md create mode 100644 src/features/product/components/README.md create mode 100644 src/features/product/composables/README.md create mode 100644 src/features/product/index.ts create mode 100644 src/features/product/router/index.ts create mode 100644 src/features/product/views/ProductDetail/ProductDetail.module.less create mode 100644 src/features/product/views/ProductDetail/ProductDetail.tsx create mode 100644 src/features/product/views/ProductList/ProductList.module.less create mode 100644 src/features/product/views/ProductList/ProductList.tsx create mode 100644 src/main.ts create mode 100644 src/shared/types/env.d.ts create mode 100644 src/shared/types/shared.d.ts create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ac4c8c6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +node_modules +dist +.git +.DS_Store +*.log +docker/ # 排除 docker 配置文件夹本身 +.editorconfig +.eslintrc.js +.prettierrc + +.vscode +.idea +*.swp +*.swo diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..6911310 --- /dev/null +++ b/.env.development @@ -0,0 +1,26 @@ +# 请求协议 http or https(建议线上配置证书后,使用https) +VITE_PREFIX=http:// + +# 内网 中的 Nacos 配置中心 ip:端口 | 域名 +#VITE_NACOS_ADDRESS=cluster.nacos.com +VITE_NACOS_ADDRESS=192.168.139.84:8848 + + +# 注册到 Nacos 的服务名称(微前端模块名称 +VITE_SERVER_NAME=app-product +# 注册到 Nacos 的端口,也是前端运行的端口 +VITE_SERVER_PORT=1301 + + +# +# 说明:项目要调用哪些 微前端 模块 +# 格式:VITE_MODEL_XXXX_NAME=微前端模块名称(模块 的 开发者提供) +# 作用:通过名称从Nacos配置中心发现模块地址和端口,给 federation 实时加载 +# + +# shared 共享资源模块 +VITE_MODEL_SHARED_NAME=app-shared + + + + diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..82ba25e --- /dev/null +++ b/.env.production @@ -0,0 +1,23 @@ +# 请求协议 http or https(建议线上配置证书后,使用https) +VITE_PREFIX=http:// + +# 内网 中的 Nacos 配置中心 ip:端口 | 域名 +#VITE_NACOS_ADDRESS=cluster.nacos.com +VITE_NACOS_ADDRESS=192.168.139.84:8848 + + +# 注册到 Nacos 的服务名称(微前端模块名称 +VITE_SERVER_NAME=app-product +# 注册到 Nacos 的端口,也是前端运行的端口 +VITE_SERVER_PORT=1301 + + +# +# 说明:项目要调用哪些 微前端 模块 +# 格式:VITE_MODEL_XXXX_NAME=微前端模块名称(模块 的 开发者提供) +# 作用:通过名称从Nacos配置中心发现模块地址和端口,给 federation 实时加载 +# + +# shared 共享资源模块 +VITE_MODEL_SHARED_NAME=app-shared + diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..567ba82 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,75 @@ +name: build and push + +# 当代码推送到 main 分支时触发 +on: + push: + branches: [ main ] + +jobs: + build-and-push: + runs-on: ubuntu-latest + + steps: + - name: 拉取最新代码 + uses: actions/checkout@v4 + + - name: 设置 Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: 登录到自己的 Docker 仓库 + uses: docker/login-action@v3 + with: + registry: registry.bmycode.help + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + + - name: 构建并推送镜像 + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + registry.bmycode.help/app-product:latest + registry.bmycode.help/app-product:${{ github.sha }} + + + - name: 替换镜像标签为 github.sha + run: | + sed -i "s|{{IMAGE_TAG}}|${{ github.sha }}|g" app-product.yml + + - name: 上传 app-product.yml 到前端集群管理机 + uses: appleboy/scp-action@v1 + with: + host: ${{ vars.SSH_MANAGE }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + port: ${{ secrets.PORT }} + source: "app-product.yml" + target: "/home/bmy/" + + - name: 登录前端集群,拉镜像 + uses: appleboy/ssh-action@v1 + with: + # 统一登录三台前端集群的linux,统一拉取刚推到仓库的最新镜像 + # 解决 Swarm 无法控制 工作机拉取镜像的问题! + host: ${{ vars.SSH_HOST_LIST }} + sync: true + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + port: ${{ secrets.PORT }} + script: | + # 拉取刚打包的最新镜像 + docker pull registry.bmycode.help/app-product:${{ github.sha }} + + - name: 管理节点部署到 Swarm + uses: appleboy/ssh-action@v1 + with: + host: ${{ vars.SSH_MANAGE }} + sync: true + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + port: ${{ secrets.PORT }} + script: | + # 切换到管理员,要不然没权限在服务器执行 docker 命令,部署到 Swarm 集群 + sudo docker stack deploy -c /home/bmy/app-product.yml app-product diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..56b3f97 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM node:24-alpine AS builder +WORKDIR /app + +COPY package.json ./ + +# 直接使用 npm install 并解决依赖问题 +RUN npm install --no-audit --no-fund --legacy-peer-deps + +# 拷贝源码并构建 +COPY . . + +# 【前端修改】如果要以子路径 /app-product/ 部署,请用 base 指定前缀,同 .env中VITE_SERVER_NAME +RUN npx vite build --base=/app-product/ + +FROM nginx:alpine +# 构建产物放到 /usr/share/nginx/html/app-product +# nginx.conf 也需要修改 +COPY --from=builder /app/dist /usr/share/nginx/html/app-product +# 覆盖 Nginx 配置,支持 SPA 子路径 +COPY docker/nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9c5e811 --- /dev/null +++ b/README.md @@ -0,0 +1,156 @@ + +## app-product 商品模块(微前端模块) + +从项目中拆分出来,用于演示的微前端模块,主要实现 商品相关功能。本案例演示中提供: + +- 调用 微前端 app-shared 模块 +- 调接口,获取商品首页的数据和展示 +- 调接口,点击商品列表进入商品详情页 + + +## 运行 + +下面文档分为**开发**和**上线**两部分进行说明!**默认前端已经在电脑上安装过 Docker 环境!!** + +> 想要【开发阶段运行】,必须 先参考下面 【上线】-【任务1】配置好两个前端自己的环境变量文件!很简单! + +### 开发 + +```bash +# 安装依赖 +npm install + +# 开发阶段 运行 项目 +# PS:注意此命令运行的项目,【无法】被其他 微前端模块 使用,仅用于本地独立开发,独立测试 +npm run dev + + +# 启动 实时打包 & 实时预览 +# PS:注意此命令运行的项目,【可以】被其他 微前端模块 调用,可用于本地开发和微前端联合开发 +npm run dep +``` + +### 上线 + +代码 到 仓库的 **main 分支** 后会触发 全程自动化,实现自动打包前端代码,构建镜像,自动部署到公司内网的Linux服务器集群中! +提交到其他分支不触发自动化操作!具体什么规则,以 技术负责人 说的为准!请遵守规则! + + +**根目录核心文件说明** + +- `app-product.yml` - Dcoker Swarm 集群部署配置【不准动】 +- `docker-compose.yml` - 开发阶段容器编排【可选,不要就删除】 +- `Dockerfile` - 打包构建前端代码为镜像【根据需求改动】 +- `nginx.conf` - 镜像内前端被访问的Nginx配置【根据需求改动】 +- `act-runner.yml` - gitea action 的 runner【根据需求改动】 + +前端工作: + +前期大致工作内容如下,改好后,以后就不用再动了,很简单: + +- 任务1: 编辑 前端 .env.development 和 .env.production 环境变量(只需修改一次) +- 任务2: 确认或编辑 Dockerfile,nginx.conf +- 任务3: 编辑 act-runner.yml + +--- + +详细展开说明: + +**任务1:** + +主要修改两个环境变量文件 `.env.development`,`.env.production` 中的: + +```bash + +# 找技术负责人要 +# 情况1: 【内网模块】填写 Nacos 内网 ip 或 域名 即可 +# 情况2: 【外网模块】填写 traefik 公网 ip 或 域名 即可 +# .env.development, .env.production 中 可以不一样! +VITE_NACOS_ADDRESS=???? + + +# 这个参数很重要,前端可以自定义填写,填写后不允许再改,填完给 技术负责人 即可 +# 微前端应用的名称,遵守 app-xxxxx +# .env.development, .env.production 中 必须一样! +VITE_SERVER_NAME=app-??? + +#【ps】其他参数看环境变量内说明 +``` + +--- + +**任务2:** + +主要修改两个 `Dockerfile`,`nginx.conf`,改起来也很简单: + + +Dockerfile 修改教程: + +```bash + + +# 将 VITE_SERVER_NAME 替换为 上一步设置的 VITE_SERVER_NAME 的 数值 即可 +RUN npx vite build --base=/VITE_SERVER_NAME/ + +# 将 VITE_SERVER_NAME 替换为 上一步设置的 VITE_SERVER_NAME 的 数值 即可 +COPY --from=builder /app/dist /usr/share/nginx/html/VITE_SERVER_NAME +``` + + +nginx.conf 修改教程: + +```bash +# 看仔细了,有三处 VITE_SERVER_NAME 需要替换成 值!! +location /VITE_SERVER_NAME/ { + alias /usr/share/nginx/html/VITE_SERVER_NAME/; + try_files $uri $uri/ /VITE_SERVER_NAME/index.html; + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; +} +``` + +--- + +**任务3:** + +act-runner.yml 是 Gitea Action 的核心,Gitea会将Job委托给Runner来运行,**所以我们前端本地必须要先运行 act-runner.yml 文件**,这样在我们提交代码的时候 Gitea Action 的自动构建才会运行!! + +但是,运行 act-runner.yml 之前,需要先对 act-runner.yml 文件进行简单的配置: + +```bash + +# 核心 需要改动的配置 +# 可以直接让 仓库 的管理员 给你把下面参数之间配置好,当然你也可以自己配 + +# GITEA_INSTANCE_URL=这个前端项目模块的 git仓库地址 +# 格式:协议://域名 即可,例如:https://git.bmycode.help 或 https://gitee.com 等 + +# 项目仓库首页-设置-Actions-Runner 右上角可复制令牌 +# GITEA_RUNNER_REGISTRATION_TOKEN=注册令牌,来源三选一:实例,组织,全存储库 +environment: + - GITEA_INSTANCE_URL=https://git.bmycode.help + - GITEA_RUNNER_REGISTRATION_TOKEN=WFiO5JDwz7CHnk7fMGJYMcSITU81CLXuI7Ofg10e + +``` + +改好后,在**项目文件夹根目录**打开终端,通过下面命令运行 act-runner.yml 文件: + +```bash +docker-compose -f act-runner.yml up -d + +# 运行后,如果 在 docker desktop 的容器中找到 名字叫:gitea-act-runner 的容器,查看日志: + +# 有下面这行,则表示 runner 成功启动!!docker desktop 可以关闭了或者放后台,不用管了! +# level=debug msg="Successfully pinged the Gitea instance server" + +# 如果出问题了,找 技术负责人! +``` + +--- + + +**到这一步,上线 配置已经搞完,很简单吧!剩下的,你提交代码到仓库就行,项目会自动构建,自动打包发布到公司内网集群中部署和运行,不用你管了!!** + + diff --git a/act-runner.yml b/act-runner.yml new file mode 100644 index 0000000..72febb6 --- /dev/null +++ b/act-runner.yml @@ -0,0 +1,17 @@ +version: '3.8' + +services: + gitea-actions-runner: + image: gitea/act_runner:latest + container_name: gitea-act-runner + restart: unless-stopped + volumes: + - runner-data:/data + - /var/run/docker.sock:/var/run/docker.sock + environment: + - GITEA_INSTANCE_URL=https://git.bmycode.help + - GITEA_RUNNER_REGISTRATION_TOKEN=WFiO5JDwz7CHnk7fMGJYMcSITU81CLXuI7Ofg10e + - GITEA_RUNNER_LABELS=ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest + +volumes: + runner-data: diff --git a/app-product.yml b/app-product.yml new file mode 100644 index 0000000..97e0705 --- /dev/null +++ b/app-product.yml @@ -0,0 +1,39 @@ +version: "3.8" # Docker Compose 文件版本,3.8 支持 Swarm 模式的所有功能 + +services: + app-product: + image: registry.bmycode.help/app-product:{{IMAGE_TAG}} + ports: + - target: 80 # 容器内部端口 + published: 1301 # 宿主机对外暴露端口 + protocol: tcp # 协议类型 + mode: ingress # 模式:使用路由网格 + deploy: + replicas: 3 # 副本数量,在集群中运行 3 个容器实例 + placement: + max_replicas_per_node: 1 # 每个 Swarm 节点最多运行 1 个副本,确保高可用性 + restart_policy: + condition: any # 重启条件:任何情况下容器退出都重启 + delay: 5s # 重启延迟 5 秒 + max_attempts: 3 # 最大重启尝试次数 + update_config: # 滚动更新配置 + parallelism: 1 # 并行更新数量:一次只更新 1 个容器 + delay: 10s # 更新间隔:每个容器更新后等待 10 秒再更新下一个 + failure_action: rollback # 更新失败时自动回滚到上一版本 + order: start-first # 更新顺序:先启动新容器,确认健康后再停止旧容器 + rollback_config: # 回滚配置 + parallelism: 1 # 回滚时并行数量 + delay: 5s # 回滚延迟 + resources: # 资源限制 + limits: # 资源上限 + cpus: "0.50" # 最多使用 0.5 个 CPU 核心 + memory: "256M" # 最多使用 256MB 内存 + reservations: # 资源预留 + cpus: "0.25" # 预留 0.25 个 CPU 核心 + memory: "128M" # 预留 128MB 内存 + networks: + - frontend # 连接到 frontend 网络 + +networks: + frontend: # 定义 frontend 网络 + driver: overlay # 使用 overlay 网络驱动,支持跨主机通信 \ No newline at end of file diff --git a/dist/assets/ProductDetail-C2SXoWRu.js b/dist/assets/ProductDetail-C2SXoWRu.js new file mode 100644 index 0000000..9900dbf --- /dev/null +++ b/dist/assets/ProductDetail-C2SXoWRu.js @@ -0,0 +1 @@ +import{importShared as u}from"./__federation_fn_import-E6wRZccp.js";import{product as d}from"./productModule-C57DerbR.js";const s="_ProductDetail_16njr_1",m="_title_16njr_1",r={ProductDetail:s,title:m},{createTextVNode:o,createVNode:e}=await u("vue"),{defineComponent:p,onMounted:P,reactive:_}=await u("vue"),{useRoute:v}=await u("vue-router"),w=p({setup(){const i=v(),c=d.createProductApplicationService(),t=_({item:{},id:0});P(()=>{if(!i.query.id)throw new Error("缺少id参数");t.id=Number(i.query.id),console.log("id: ",t.id),a()});const a=async()=>{t.item=await c.getProductInfo(t.id),console.log("state.item: ",t.item)};return()=>e("div",{class:r.ProductDetail},[e("h1",{class:r.title},[o("商品领域模块 - 商品详情页面")]),e("hr",null,null),e("p",null,[o("商品id:"),t.id]),t.item.name,e("ul",null,[Object.entries(t.item).map(([l,n])=>e("li",null,[l,o(": "),n]))])])}});export{w as default}; diff --git a/dist/assets/ProductDetail-rjscZczN.css b/dist/assets/ProductDetail-rjscZczN.css new file mode 100644 index 0000000..cb43c4e --- /dev/null +++ b/dist/assets/ProductDetail-rjscZczN.css @@ -0,0 +1 @@ +._ProductDetail_16njr_1 ._title_16njr_1{color:#00f} diff --git a/dist/assets/ProductList-BnGJM5LT.js b/dist/assets/ProductList-BnGJM5LT.js new file mode 100644 index 0000000..15c9e2d --- /dev/null +++ b/dist/assets/ProductList-BnGJM5LT.js @@ -0,0 +1 @@ +import{importShared as r}from"./__federation_fn_import-E6wRZccp.js";import{__federation_method_getRemote as i}from"./__federation_expose_ProductDomain-J98eKK33.js";import{product as p}from"./productModule-C57DerbR.js";const _="_ProductList_1t3dn_1",E="_test_1t3dn_1",s={ProductList:_,test:E},{createVNode:t,createTextVNode:e}=await r("vue"),{defineComponent:m,onMounted:C,reactive:f}=await r("vue"),{useRouter:h}=await r("vue-router"),v=await i("shared","./element-plus");let{ElCard:P,ElIcon:F,Icons:L}=v;const x=m({setup(){const a=h(),n=p.createProductApplicationService(),o=f({list:[]});C(()=>{c()});const c=async()=>{o.list=await n.getProductList(),console.log("state.list: ",o.list)},d=()=>t("div",{class:"card-header"},[t(F,{size:15},{default:()=>[t(L.Position,null,null)]}),t("span",null,[e("Card 头部")])]),l=()=>t("div",null,[e("Footer 底部")]);return()=>t("div",{class:s.ProductList},[t("h1",{class:s.test},[e("商品领域模块 - 商品列表页面3")]),t("hr",null,null),t("h2",null,[e("从Deno 后端 加载的数据,点击进详情")]),t(P,null,{header:()=>d(),footer:()=>l(),default:()=>o.list.map(u=>t("p",{key:u.id,onClick:()=>{a.push({name:"ProductDetail",query:{id:u.id}})}},[u.id,e(" | "),u.name,e(" | ¥"),u.price]))})])}});export{x as default}; diff --git a/dist/assets/ProductList-CV-Muv1j.css b/dist/assets/ProductList-CV-Muv1j.css new file mode 100644 index 0000000..54cd71d --- /dev/null +++ b/dist/assets/ProductList-CV-Muv1j.css @@ -0,0 +1 @@ +._ProductList_1t3dn_1 ._test_1t3dn_1{color:var(--theme-color)} diff --git a/dist/assets/__federation_expose_ProductDomain-J98eKK33.js b/dist/assets/__federation_expose_ProductDomain-J98eKK33.js new file mode 100644 index 0000000..4a6a0b4 --- /dev/null +++ b/dist/assets/__federation_expose_ProductDomain-J98eKK33.js @@ -0,0 +1 @@ +var o=(e=>(e.PriceNotNegativein="商品 价格 不能为负数",e.StockNotNegativein="商品 库存 不能为负数",e.StockIsGreaterThanZero="减少的库存数量必须大于0",e.LowStock="库存不足",e.IdNotNull="商品Id不能为空",e))(o||{});class I{constructor(t){this.productRepository=t}async getProductList(){return await this.productRepository.findAll()}async getProductInfo(t){if(!t)throw new Error(o.IdNotNull);return await this.productRepository.findById(t)}}class c{_id;_name;_description;_price;_imageUrl;_stock;_categoryId;constructor(t,r,i,_,a,s,n){this._id=t,this._name=r,this._description=i,this._price=_,this._imageUrl=a,this._stock=s,this._categoryId=n}get id(){return this._id}get name(){return this._name}set name(t){this._name=t}get description(){return this._description}set description(t){this._description=t}get price(){return this._price}set price(t){if(t<0)throw new Error(o.PriceNotNegativein);this._price=t}get imageUrl(){return this._imageUrl}set imageUrl(t){this._imageUrl=t}get stock(){return this._stock}set stock(t){if(t<0)throw new Error(o.StockNotNegativein);this._stock=t}get categoryId(){return this._categoryId}set categoryId(t){this._categoryId=t}hasStock(){return this._stock>0}reduceStock(t){if(t<=0)throw new Error(o.StockIsGreaterThanZero);if(this._stock()=>r)}function l(e,t){const r=Object.assign(e,t);for(const i of Object.keys(r))typeof r[i]=="object"&&typeof t[i]=="object"&&(r[i]=l(r[i],t[i]));return r}const f=e=>l({vue:{undefined:{get:()=>d(new URL("__federation_shared_vue-CmZhWQPe.js",import.meta.url).href),loaded:1}},"vue-router":{undefined:{get:()=>d(new URL("__federation_shared_vue-router-CUrgpNf2.js",import.meta.url).href),loaded:1}},pinia:{undefined:{get:()=>d(new URL("__federation_shared_pinia-o7RAmTGs.js",import.meta.url).href),loaded:1}}},(globalThis.__federation_shared__||{}).default||{});async function g(e){return u[e]??=import(e),u[e]}async function y(e){const t=m[e];if(t.inited)return t.lib;if(["esm","systemjs"].includes(t.format))return new Promise((r,i)=>{Promise.resolve(t.url).then(a=>{import(a).then(s=>{if(!t.inited){const n=f();s.init(n),t.lib=s,t.lib.init(n),t.inited=!0}r(t.lib)}).catch(i)})})}function w(e,t){return y(e).then(r=>r.get(t).then(i=>i()))}class h{static apiUrlList={productsListUrl:"/productsList",productsInfoUrl:"/productsInfo"}}const k=await w("shared","./infra");let{http:p}=k;class U{async findAll(){return(await p.get({url:h.apiUrlList.productsListUrl})).map(i=>c.fromDTO(i))}async findById(t){const r=await p.get({url:h.apiUrlList.productsInfoUrl,data:{id:t}});return c.fromDTO(r)}}export{o as ErrorText,U as HttpProductRepository,c as Product,I as ProductApplicationService,w as __federation_method_getRemote}; diff --git a/dist/assets/__federation_expose_ProductRouter-BB_8fJdP.js b/dist/assets/__federation_expose_ProductRouter-BB_8fJdP.js new file mode 100644 index 0000000..e59b1ab --- /dev/null +++ b/dist/assets/__federation_expose_ProductRouter-BB_8fJdP.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ProductList-BnGJM5LT.js","assets/__federation_fn_import-E6wRZccp.js","assets/__federation_expose_ProductDomain-J98eKK33.js","assets/productModule-C57DerbR.js","assets/ProductList-CV-Muv1j.css","assets/ProductDetail-C2SXoWRu.js","assets/ProductDetail-rjscZczN.css"])))=>i.map(i=>d[i]); +const E="modulepreload",P=function(i){return"/app-product/"+i},u={},d=function(m,s,v){let l=Promise.resolve();if(s&&s.length>0){let p=function(e){return Promise.all(e.map(o=>Promise.resolve(o).then(c=>({status:"fulfilled",value:c}),c=>({status:"rejected",reason:c}))))};document.getElementsByTagName("link");const n=document.querySelector("meta[property=csp-nonce]"),t=n?.nonce||n?.getAttribute("nonce");l=p(s.map(e=>{if(e=P(e),e in u)return;u[e]=!0;const o=e.endsWith(".css"),c=o?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${e}"]${c}`))return;const r=document.createElement("link");if(r.rel=o?"stylesheet":E,o||(r.as="script"),r.crossOrigin="",r.href=e,t&&r.setAttribute("nonce",t),document.head.appendChild(r),o)return new Promise((f,h)=>{r.addEventListener("load",f),r.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${e}`)))})}))}function a(n){const t=new Event("vite:preloadError",{cancelable:!0});if(t.payload=n,window.dispatchEvent(t),!t.defaultPrevented)throw n}return l.then(n=>{for(const t of n||[])t.status==="rejected"&&a(t.reason);return m().catch(a)})},_=[{path:"/Products",name:"ProductList",component:()=>d(()=>import("./ProductList-BnGJM5LT.js"),__vite__mapDeps([0,1,2,3,4])),meta:{title:"商品列表"}},{path:"/ProductDetail",name:"ProductDetail",component:()=>d(()=>import("./ProductDetail-C2SXoWRu.js"),__vite__mapDeps([5,1,3,2,6])),meta:{title:"商品详情"}}];export{_ as productRouter}; diff --git a/dist/assets/__federation_fn_import-E6wRZccp.js b/dist/assets/__federation_fn_import-E6wRZccp.js new file mode 100644 index 0000000..d5761a0 --- /dev/null +++ b/dist/assets/__federation_fn_import-E6wRZccp.js @@ -0,0 +1 @@ +const L="[0-9A-Za-z-]+",P=`(?:\\+(${L}(?:\\.${L})*))`,R="0|[1-9]\\d*",_="[0-9]+",Z="\\d*[a-zA-Z-][a-zA-Z0-9-]*",S=`(?:${_}|${Z})`,N=`(?:-?(${S}(?:\\.${S})*))`,X=`(?:${R}|${Z})`,k=`(?:-(${X}(?:\\.${X})*))`,w=`${R}|x|X|\\*`,d=`[v=\\s]*(${w})(?:\\.(${w})(?:\\.(${w})(?:${k})?${P}?)?)?`,D=`^\\s*(${d})\\s+-\\s+(${d})\\s*$`,J=`(${_})\\.(${_})\\.(${_})`,Q=`[v=\\s]*${J}${N}?${P}?`,y="((?:<|>)?=?)",U=`(\\s*)${y}\\s*(${Q}|${d})`,F="(?:~>?)",W=`(\\s*)${F}\\s+`,K="(?:\\^)",Y=`(\\s*)${K}\\s+`,A="(<|>)?=?\\s*\\*",j=`^${K}${d}$`,m=`(${R})\\.(${R})\\.(${R})`,ee=`v?${m}${k}?${P}?`,re=`^${F}${d}$`,ne=`^${y}\\s*${d}$`,se=`^${y}\\s*(${ee})$|^$`,te="^\\s*>=\\s*0.0.0\\s*$";function o(e){return new RegExp(e)}function c(e){return!e||e.toLowerCase()==="x"||e==="*"}function B(...e){return s=>e.reduce((t,r)=>r(t),s)}function E(e){return e.match(o(se))}function z(e,s,t,r){const n=`${e}.${s}.${t}`;return r?`${n}-${r}`:n}function ie(e){return e.replace(o(D),(s,t,r,n,i,$,u,f,a,l,V,p)=>(c(r)?t="":c(n)?t=`>=${r}.0.0`:c(i)?t=`>=${r}.${n}.0`:t=`>=${t}`,c(a)?f="":c(l)?f=`<${+a+1}.0.0-0`:c(V)?f=`<${a}.${+l+1}.0-0`:p?f=`<=${a}.${l}.${V}-${p}`:f=`<=${f}`,`${t} ${f}`.trim()))}function $e(e){return e.replace(o(U),"$1$2$3")}function ue(e){return e.replace(o(W),"$1~")}function ce(e){return e.replace(o(Y),"$1^")}function fe(e){return e.trim().split(/\s+/).map(s=>s.replace(o(j),(t,r,n,i,$)=>c(r)?"":c(n)?`>=${r}.0.0 <${+r+1}.0.0-0`:c(i)?r==="0"?`>=${r}.${n}.0 <${r}.${+n+1}.0-0`:`>=${r}.${n}.0 <${+r+1}.0.0-0`:$?r==="0"?n==="0"?`>=${r}.${n}.${i}-${$} <${r}.${n}.${+i+1}-0`:`>=${r}.${n}.${i}-${$} <${r}.${+n+1}.0-0`:`>=${r}.${n}.${i}-${$} <${+r+1}.0.0-0`:r==="0"?n==="0"?`>=${r}.${n}.${i} <${r}.${n}.${+i+1}-0`:`>=${r}.${n}.${i} <${r}.${+n+1}.0-0`:`>=${r}.${n}.${i} <${+r+1}.0.0-0`)).join(" ")}function ae(e){return e.trim().split(/\s+/).map(s=>s.replace(o(re),(t,r,n,i,$)=>c(r)?"":c(n)?`>=${r}.0.0 <${+r+1}.0.0-0`:c(i)?`>=${r}.${n}.0 <${r}.${+n+1}.0-0`:$?`>=${r}.${n}.${i}-${$} <${r}.${+n+1}.0-0`:`>=${r}.${n}.${i} <${r}.${+n+1}.0-0`)).join(" ")}function le(e){return e.split(/\s+/).map(s=>s.trim().replace(o(ne),(t,r,n,i,$,u)=>{const f=c(n),a=f||c(i),l=a||c($);return r==="="&&l&&(r=""),u="",f?r===">"||r==="<"?"<0.0.0-0":"*":r&&l?(a&&(i=0),$=0,r===">"?(r=">=",a?(n=+n+1,i=0,$=0):(i=+i+1,$=0)):r==="<="&&(r="<",a?n=+n+1:i=+i+1),r==="<"&&(u="-0"),`${r+n}.${i}.${$}${u}`):a?`>=${n}.0.0${u} <${+n+1}.0.0-0`:l?`>=${n}.${i}.0${u} <${n}.${+i+1}.0-0`:t})).join(" ")}function oe(e){return e.trim().replace(o(A),"")}function pe(e){return e.trim().replace(o(te),"")}function b(e,s){return e=+e||e,s=+s||s,e>s?1:e===s?0:-1}function de(e,s){const{preRelease:t}=e,{preRelease:r}=s;if(t===void 0&&r)return 1;if(t&&r===void 0)return-1;if(t===void 0&&r===void 0)return 0;for(let n=0,i=t.length;n<=i;n++){const $=t[n],u=r[n];if($!==u)return $===void 0&&u===void 0?0:$?u?b($,u):-1:1}return 0}function v(e,s){return b(e.major,s.major)||b(e.minor,s.minor)||b(e.patch,s.patch)||de(e,s)}function x(e,s){return e.version===s.version}function Re(e,s){switch(e.operator){case"":case"=":return x(e,s);case">":return v(e,s)<0;case">=":return x(e,s)||v(e,s)<0;case"<":return v(e,s)>0;case"<=":return x(e,s)||v(e,s)>0;case void 0:return!0;default:return!1}}function Ve(e){return B(fe,ae,le,oe)(e)}function ve(e){return B(ie,$e,ue,ce)(e.trim()).split(/\s+/).join(" ")}function _e(e,s){if(!e)return!1;const n=ve(s).split(" ").map(p=>Ve(p)).join(" ").split(/\s+/).map(p=>pe(p)),i=E(e);if(!i)return!1;const[,$,,u,f,a,l]=i,V={version:z(u,f,a,l),major:u,minor:f,patch:a,preRelease:l?.split(".")};for(const p of n){const g=E(p);if(!g)return!1;const[,H,,O,q,I,h]=g,M={operator:H,version:z(O,q,I,h),major:O,minor:q,patch:I,preRelease:h?.split(".")};if(!Re(M,V))return!1}return!0}const C={},T=Object.create(null);async function he(e,s="default"){return T[e]?new Promise(t=>t(T[e])):await be(e,s)||Te(e)}async function be(e,s){let t=null;if(globalThis?.__federation_shared__?.[s]?.[e]){const r=globalThis.__federation_shared__[s][e],n=C[e]?.requiredVersion;if(!!n){const $=Object.keys(r).find(u=>_e(u,n));$?t=await(await r[$].get())():console.log(`provider support ${e}(${$}) is not satisfied requiredVersion(\${moduleMap[name].requiredVersion})`)}else{const $=Object.keys(r)[0];t=await(await r[$].get())()}}if(t)return G(t,e)}async function Te(e){if(C[e]?.import){let s=await(await C[e].get())();return G(s,e)}else console.error("consumer config import=false,so cant use callback shared module")}function G(e,s){return typeof e.default=="function"?(Object.keys(e).forEach(t=>{t!=="default"&&(e.default[t]=e[t])}),T[s]=e.default,e.default):(e.default&&(e=Object.assign({},e.default,e)),T[s]=e,e)}export{he as importShared,Te as importSharedLocal,be as importSharedRuntime}; diff --git a/dist/assets/index-KMVTlfvo.js b/dist/assets/index-KMVTlfvo.js new file mode 100644 index 0000000..71b20c8 --- /dev/null +++ b/dist/assets/index-KMVTlfvo.js @@ -0,0 +1 @@ +import{importShared as l}from"./__federation_fn_import-E6wRZccp.js";(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))c(e);new MutationObserver(e=>{for(const t of e)if(t.type==="childList")for(const i of t.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&c(i)}).observe(document,{childList:!0,subtree:!0});function s(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?t.credentials="include":e.crossOrigin==="anonymous"?t.credentials="omit":t.credentials="same-origin",t}function c(e){if(e.ep)return;e.ep=!0;const t=s(e);fetch(e.href,t)}})();const u={BASE_URL:"/app-product/",DEV:!1,MODE:"production",PROD:!0,SSR:!1,VITE_MODEL_SHARED_NAME:"app-shared",VITE_NACOS_ADDRESS:"192.168.139.84:8848",VITE_PREFIX:"http://",VITE_SERVER_NAME:"app-product",VITE_SERVER_PORT:"1301"},{defineComponent:a,onMounted:p,Fragment:d,createTextVNode:o,createVNode:r}=await l("vue"),f=a({setup(){return p(()=>{console.log("import.meta.env: ",u)}),()=>r(d,null,[r("div",{class:"order-federation-placeholder"},[r("h2",null,[o("商品-联邦模块")]),r("p",null,[o("此页面仅用于 商品模块 的单独开发和调试,可临时引入组件进行本地测试,实际运行时由 主应用 加载本项目代码")]),r("h2",null,[o("本模块包含的功能:")]),r("ul",null,[r("li",null,[o("1:获取商品首页的数据和展示")]),r("li",null,[o("2:点击商品进入详情页")])]),r("p",null,null)])])}}),{createApp:m}=await l("vue"),{createPinia:_}=await l("pinia");m(f).use(_()).mount("#app"); diff --git a/dist/assets/productModule-C57DerbR.js b/dist/assets/productModule-C57DerbR.js new file mode 100644 index 0000000..d7912b5 --- /dev/null +++ b/dist/assets/productModule-C57DerbR.js @@ -0,0 +1 @@ +import{ProductApplicationService as r,HttpProductRepository as t}from"./__federation_expose_ProductDomain-J98eKK33.js";const o={bindProductRepository:()=>new t,createProductApplicationService:()=>new r(o.bindProductRepository())};export{o as product}; diff --git a/dist/assets/remoteEntry.js b/dist/assets/remoteEntry.js new file mode 100644 index 0000000..c5c5841 --- /dev/null +++ b/dist/assets/remoteEntry.js @@ -0,0 +1 @@ +const p={},b=new Set(["Module","__esModule","default","_export_sfc"]);let g={"./ProductDomain":()=>(y([],!1,"./ProductDomain"),D("/app-product/assets/__federation_expose_ProductDomain-J98eKK33.js").then(e=>Object.keys(e).every(r=>b.has(r))?()=>e.default:()=>e)),"./ProductRouter":()=>(y([],!1,"./ProductRouter"),D("/app-product/assets/__federation_expose_ProductRouter-BB_8fJdP.js").then(e=>Object.keys(e).every(r=>b.has(r))?()=>e.default:()=>e))};const m={},y=(e,r,c)=>{const s=import.meta.url;if(typeof s>"u"){console.warn('The remote style takes effect only when the build.target option in the vite.config.ts file is higher than that of "es2020".');return}const i=s.substring(0,s.lastIndexOf("remoteEntry.js")),_='/app-product/';'assets',e.forEach(a=>{let o="";const l=_||i;if(l){const n={trailing:t=>t.endsWith("/")?t.slice(0,-1):t,leading:t=>t.startsWith("/")?t.slice(1):t},E=t=>t.startsWith("http")||t.startsWith("//"),f=n.trailing(l),u=n.leading(a),h=n.trailing(i);E(l)?o=[f,u].filter(Boolean).join("/"):h.includes(f)?o=[h,u].filter(Boolean).join("/"):o=[h+f,u].filter(Boolean).join("/")}else o=a;if(r){const n="css__app-product__"+c;window[n]=window[n]||[],window[n].push(o);return}if(o in m)return;m[o]=!0;const d=document.createElement("link");d.rel="stylesheet",d.href=o,document.head.appendChild(d)})};async function D(e){return p[e]??=import(e),p[e]}const w=e=>{if(!g[e])throw new Error("Can not find remote module "+e);return g[e]()},T=e=>{globalThis.__federation_shared__=globalThis.__federation_shared__||{},Object.entries(e).forEach(([r,c])=>{for(const[s,i]of Object.entries(c)){const _=i.scope||"default";globalThis.__federation_shared__[_]=globalThis.__federation_shared__[_]||{};const a=globalThis.__federation_shared__[_];(a[r]=a[r]||{})[s]=i}})};export{y as dynamicLoadingCss,w as get,T as init}; diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..2c0df28 --- /dev/null +++ b/dist/index.html @@ -0,0 +1,17 @@ + + + + + + + + Vite App + + + + + +
+ + + \ No newline at end of file diff --git a/dist/stats.html b/dist/stats.html new file mode 100644 index 0000000..ad16178 --- /dev/null +++ b/dist/stats.html @@ -0,0 +1,4949 @@ + + + + + + + + 商品模块依赖分析 + + + +
+ + + + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3425db9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: "3.8" + +services: + app-product: + build: + context: .. + dockerfile: docker/Dockerfile + + image: registry.bmycode.help/app-product:latest + container_name: app-product + ports: + - "1301:80" + restart: unless-stopped diff --git a/index.html b/index.html new file mode 100644 index 0000000..29d8565 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + + Vite App + + + +
+ + + + \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..bd5a27d --- /dev/null +++ b/nginx.conf @@ -0,0 +1,14 @@ +server { + listen 80; + server_name *.ddd.com; + + + location /app-product/ { + alias /usr/share/nginx/html/app-product/; + try_files $uri $uri/ /app-product/index.html; + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; + } +} \ No newline at end of file diff --git a/node_modules/.bin/browserslist b/node_modules/.bin/browserslist new file mode 100755 index 0000000..bb6afae --- /dev/null +++ b/node_modules/.bin/browserslist @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/browserslist@4.26.3/node_modules/browserslist/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/browserslist@4.26.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/browserslist@4.26.3/node_modules/browserslist/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/browserslist@4.26.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/browserslist@4.26.3/node_modules/browserslist/cli.js" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/browserslist@4.26.3/node_modules/browserslist/cli.js" "$@" +fi diff --git a/node_modules/.bin/lessc b/node_modules/.bin/lessc new file mode 100755 index 0000000..fefc282 --- /dev/null +++ b/node_modules/.bin/lessc @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/less@4.4.1/node_modules/less/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/less@4.4.1/node_modules/less/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/less@4.4.1/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/less@4.4.1/node_modules/less/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/less@4.4.1/node_modules/less/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/less@4.4.1/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/less@4.4.1/node_modules/less/bin/lessc" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/less@4.4.1/node_modules/less/bin/lessc" "$@" +fi diff --git a/node_modules/.bin/npm-run-all b/node_modules/.bin/npm-run-all new file mode 100755 index 0000000..98c7206 --- /dev/null +++ b/node_modules/.bin/npm-run-all @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/npm-run-all/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/npm-run-all/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/npm-run-all/index.js" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/npm-run-all/index.js" "$@" +fi diff --git a/node_modules/.bin/npm-run-all2 b/node_modules/.bin/npm-run-all2 new file mode 100755 index 0000000..98c7206 --- /dev/null +++ b/node_modules/.bin/npm-run-all2 @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/npm-run-all/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/npm-run-all/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/npm-run-all/index.js" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/npm-run-all/index.js" "$@" +fi diff --git a/node_modules/.bin/rollup b/node_modules/.bin/rollup new file mode 100755 index 0000000..3f16bfb --- /dev/null +++ b/node_modules/.bin/rollup @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup@4.52.3/node_modules/rollup/dist/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup@4.52.3/node_modules/rollup/dist/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup@4.52.3/node_modules/rollup/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup@4.52.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup@4.52.3/node_modules/rollup/dist/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup@4.52.3/node_modules/rollup/dist/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup@4.52.3/node_modules/rollup/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup@4.52.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/rollup@4.52.3/node_modules/rollup/dist/bin/rollup" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/rollup@4.52.3/node_modules/rollup/dist/bin/rollup" "$@" +fi diff --git a/node_modules/.bin/rollup-plugin-visualizer b/node_modules/.bin/rollup-plugin-visualizer new file mode 100755 index 0000000..7138352 --- /dev/null +++ b/node_modules/.bin/rollup-plugin-visualizer @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer/dist/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer/dist/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer/dist/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer/dist/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer/dist/bin/cli.js" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer/dist/bin/cli.js" "$@" +fi diff --git a/node_modules/.bin/run-p b/node_modules/.bin/run-p new file mode 100755 index 0000000..cb5ca1a --- /dev/null +++ b/node_modules/.bin/run-p @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/run-p/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/run-p/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/run-p/index.js" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/run-p/index.js" "$@" +fi diff --git a/node_modules/.bin/run-s b/node_modules/.bin/run-s new file mode 100755 index 0000000..5a27767 --- /dev/null +++ b/node_modules/.bin/run-s @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/run-s/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/run-s/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/npm-run-all2@8.0.4/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/run-s/index.js" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2/bin/run-s/index.js" "$@" +fi diff --git a/node_modules/.bin/tsc b/node_modules/.bin/tsc new file mode 100755 index 0000000..621b70e --- /dev/null +++ b/node_modules/.bin/tsc @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@" +fi diff --git a/node_modules/.bin/tsserver b/node_modules/.bin/tsserver new file mode 100755 index 0000000..e467671 --- /dev/null +++ b/node_modules/.bin/tsserver @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@" +fi diff --git a/node_modules/.bin/vite b/node_modules/.bin/vite new file mode 100755 index 0000000..e850474 --- /dev/null +++ b/node_modules/.bin/vite @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules/vite/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules/vite/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules/vite/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules/vite/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules/vite/bin/vite.js" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules/vite/bin/vite.js" "$@" +fi diff --git a/node_modules/.bin/vue-tsc b/node_modules/.bin/vue-tsc new file mode 100755 index 0000000..7ebe103 --- /dev/null +++ b/node_modules/.bin/vue-tsc @@ -0,0 +1,21 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules/vue-tsc/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules/vue-tsc/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/Users/bmy/Desktop/DDD/node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules/vue-tsc/bin/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules/vue-tsc/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules:/Users/bmy/Desktop/DDD/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules/vue-tsc/bin/vue-tsc.js" "$@" +else + exec node "$basedir/../../../../node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules/vue-tsc/bin/vue-tsc.js" "$@" +fi diff --git a/node_modules/@element-plus/icons-vue b/node_modules/@element-plus/icons-vue new file mode 120000 index 0000000..1153bba --- /dev/null +++ b/node_modules/@element-plus/icons-vue @@ -0,0 +1 @@ +../../../../node_modules/.pnpm/@element-plus+icons-vue@2.3.2_vue@3.5.22_typescript@5.9.3_/node_modules/@element-plus/icons-vue \ No newline at end of file diff --git a/node_modules/@tsconfig/node22 b/node_modules/@tsconfig/node22 new file mode 120000 index 0000000..f353b4e --- /dev/null +++ b/node_modules/@tsconfig/node22 @@ -0,0 +1 @@ +../../../../node_modules/.pnpm/@tsconfig+node22@22.0.2/node_modules/@tsconfig/node22 \ No newline at end of file diff --git a/node_modules/@types/node b/node_modules/@types/node new file mode 120000 index 0000000..6390637 --- /dev/null +++ b/node_modules/@types/node @@ -0,0 +1 @@ +../../../../node_modules/.pnpm/@types+node@24.6.1/node_modules/@types/node \ No newline at end of file diff --git a/node_modules/@vitejs/plugin-vue b/node_modules/@vitejs/plugin-vue new file mode 120000 index 0000000..725fde4 --- /dev/null +++ b/node_modules/@vitejs/plugin-vue @@ -0,0 +1 @@ +../../../../node_modules/.pnpm/@vitejs+plugin-vue@6.0.1_vite@7.1.7_@types+node@24.6.1_less@4.4.1__vue@3.5.22_typescript@5.9.3_/node_modules/@vitejs/plugin-vue \ No newline at end of file diff --git a/node_modules/@vitejs/plugin-vue-jsx b/node_modules/@vitejs/plugin-vue-jsx new file mode 120000 index 0000000..b924dd0 --- /dev/null +++ b/node_modules/@vitejs/plugin-vue-jsx @@ -0,0 +1 @@ +../../../../node_modules/.pnpm/@vitejs+plugin-vue-jsx@5.1.1_vite@7.1.7_@types+node@24.6.1_less@4.4.1__vue@3.5.22_typescript@5.9.3_/node_modules/@vitejs/plugin-vue-jsx \ No newline at end of file diff --git a/node_modules/@vue/tsconfig b/node_modules/@vue/tsconfig new file mode 120000 index 0000000..fcbd5d1 --- /dev/null +++ b/node_modules/@vue/tsconfig @@ -0,0 +1 @@ +../../../../node_modules/.pnpm/@vue+tsconfig@0.8.1_typescript@5.9.3_vue@3.5.22_typescript@5.9.3_/node_modules/@vue/tsconfig \ No newline at end of file diff --git a/node_modules/element-plus b/node_modules/element-plus new file mode 120000 index 0000000..5612a4f --- /dev/null +++ b/node_modules/element-plus @@ -0,0 +1 @@ +../../../node_modules/.pnpm/element-plus@2.11.4_vue@3.5.22_typescript@5.9.3_/node_modules/element-plus \ No newline at end of file diff --git a/node_modules/less b/node_modules/less new file mode 120000 index 0000000..aec6a92 --- /dev/null +++ b/node_modules/less @@ -0,0 +1 @@ +../../../node_modules/.pnpm/less@4.4.1/node_modules/less \ No newline at end of file diff --git a/node_modules/npm-run-all2 b/node_modules/npm-run-all2 new file mode 120000 index 0000000..4db7347 --- /dev/null +++ b/node_modules/npm-run-all2 @@ -0,0 +1 @@ +../../../node_modules/.pnpm/npm-run-all2@8.0.4/node_modules/npm-run-all2 \ No newline at end of file diff --git a/node_modules/pinia b/node_modules/pinia new file mode 120000 index 0000000..3cba7ab --- /dev/null +++ b/node_modules/pinia @@ -0,0 +1 @@ +../../../node_modules/.pnpm/pinia@3.0.3_typescript@5.9.3_vue@3.5.22_typescript@5.9.3_/node_modules/pinia \ No newline at end of file diff --git a/node_modules/rollup-plugin-visualizer b/node_modules/rollup-plugin-visualizer new file mode 120000 index 0000000..ae855b2 --- /dev/null +++ b/node_modules/rollup-plugin-visualizer @@ -0,0 +1 @@ +../../../node_modules/.pnpm/rollup-plugin-visualizer@6.0.3_rollup@4.52.3/node_modules/rollup-plugin-visualizer \ No newline at end of file diff --git a/node_modules/typescript b/node_modules/typescript new file mode 120000 index 0000000..949dba4 --- /dev/null +++ b/node_modules/typescript @@ -0,0 +1 @@ +../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript \ No newline at end of file diff --git a/node_modules/vite b/node_modules/vite new file mode 120000 index 0000000..16ed767 --- /dev/null +++ b/node_modules/vite @@ -0,0 +1 @@ +../../../node_modules/.pnpm/vite@7.1.7_@types+node@24.6.1_less@4.4.1/node_modules/vite \ No newline at end of file diff --git a/node_modules/vite-federation b/node_modules/vite-federation new file mode 120000 index 0000000..058a687 --- /dev/null +++ b/node_modules/vite-federation @@ -0,0 +1 @@ +../../../node_modules/.pnpm/vite-federation@3.4.4/node_modules/vite-federation \ No newline at end of file diff --git a/node_modules/vite-plugin-nacos b/node_modules/vite-plugin-nacos new file mode 120000 index 0000000..848d694 --- /dev/null +++ b/node_modules/vite-plugin-nacos @@ -0,0 +1 @@ +../../../node_modules/.pnpm/vite-plugin-nacos@1.1.3/node_modules/vite-plugin-nacos \ No newline at end of file diff --git a/node_modules/vite-plugin-vue-devtools b/node_modules/vite-plugin-vue-devtools new file mode 120000 index 0000000..a9ba590 --- /dev/null +++ b/node_modules/vite-plugin-vue-devtools @@ -0,0 +1 @@ +../../../node_modules/.pnpm/vite-plugin-vue-devtools@8.0.2_vite@7.1.7_@types+node@24.6.1_less@4.4.1__vue@3.5.22_typescript@5.9.3_/node_modules/vite-plugin-vue-devtools \ No newline at end of file diff --git a/node_modules/vue b/node_modules/vue new file mode 120000 index 0000000..bc7d864 --- /dev/null +++ b/node_modules/vue @@ -0,0 +1 @@ +../../../node_modules/.pnpm/vue@3.5.22_typescript@5.9.3/node_modules/vue \ No newline at end of file diff --git a/node_modules/vue-router b/node_modules/vue-router new file mode 120000 index 0000000..e265f5d --- /dev/null +++ b/node_modules/vue-router @@ -0,0 +1 @@ +../../../node_modules/.pnpm/vue-router@4.5.1_vue@3.5.22_typescript@5.9.3_/node_modules/vue-router \ No newline at end of file diff --git a/node_modules/vue-tsc b/node_modules/vue-tsc new file mode 120000 index 0000000..15adb1f --- /dev/null +++ b/node_modules/vue-tsc @@ -0,0 +1 @@ +../../../node_modules/.pnpm/vue-tsc@3.1.0_typescript@5.9.3/node_modules/vue-tsc \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..0fbb814 --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "app-product", + "version": "0.0.0", + "private": true, + "type": "module", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "scripts": { + "dev": "vite", + "dep": "concurrently \"vite build --watch\" \"sleep 5 && npm run preview\"", + "preview": "vite preview --port 1301 --strictPort", + "build": "vite build", + "type-check": "vue-tsc --build" + }, + "dependencies": { + "less": "^4.4.1", + "pinia": "^3.0.3", + "vite-plugin-nacos": "^1.1.3", + "vue": "^3.5.22", + "vue-router": "^4.5.1" + }, + "devDependencies": { + "@element-plus/icons-vue": "^2.3.2", + "@tsconfig/node22": "^22.0.2", + "@types/node": "^24.6.1", + "@vitejs/plugin-vue": "^6.0.1", + "@vitejs/plugin-vue-jsx": "^5.1.1", + "@vue/tsconfig": "^0.8.1", + "element-plus": "^2.11.4", + "npm-run-all2": "^8.0.4", + "rollup-plugin-visualizer": "^6.0.3", + "typescript": "~5.9.3", + "vite": "^7.1.7", + "vite-federation": "^3.4.4", + "vite-plugin-vue-devtools": "^8.0.2", + "vue-tsc": "^3.1.0" + } +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..8fa3b43 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,27 @@ +import { defineComponent, onMounted } from 'vue' + +export default defineComponent({ + setup() { + + onMounted(() => { + console.log("import.meta.env: ", import.meta.env) + }) + + return () => ( + <> +
+

商品-联邦模块

+

此页面仅用于 商品模块 的单独开发和调试,可临时引入组件进行本地测试,实际运行时由 主应用 + 加载本项目代码

+ +

本模块包含的功能:

+
    +
  • 1:获取商品首页的数据和展示
  • +
  • 2:点击商品进入详情页
  • +
+

+
+ + ) + } +}) \ No newline at end of file diff --git a/src/domains/product/application/services/ProductApplicationService.ts b/src/domains/product/application/services/ProductApplicationService.ts new file mode 100644 index 0000000..aa42975 --- /dev/null +++ b/src/domains/product/application/services/ProductApplicationService.ts @@ -0,0 +1,22 @@ +import { ErrorText } from "../../domain/enums/ErrorEnums"; +import { ProductRepository } from "../../ports/repositories/ProductRepository"; + +/** + * 商品应用服务 - 协调领域对象完成业务用例 + * 应用服务是领域层的外观,封装了领域逻辑的调用 + */ +export class ProductApplicationService { + // 依赖注入仓储接口,而不是具体实现 + constructor(private productRepository: ProductRepository) { } + + async getProductList() { + return await this.productRepository.findAll(); + } + + async getProductInfo(id: number) { + if (!id) { + throw new Error(ErrorText.IdNotNull) + } + return await this.productRepository.findById(id); + } +} \ No newline at end of file diff --git a/src/domains/product/di/productModule.ts b/src/domains/product/di/productModule.ts new file mode 100644 index 0000000..ee041aa --- /dev/null +++ b/src/domains/product/di/productModule.ts @@ -0,0 +1,38 @@ +// 从商品联邦模块导入领域层资源 +import {ProductRepository} from "@domains/product/ports/repositories/ProductRepository"; +import {HttpProductRepository} from "@domains/product/infr/api/HttpProductRepository"; +import {ProductApplicationService} from "@domains/product/application/services/ProductApplicationService"; + +/** + * 商品领域的依赖注入配置 + * 将 接口 与 具体实现 绑定 + * + * 优点:是一个依赖工厂,它隐藏了对象创建的细节, + * 让业务代码只需要关心 “做什么”,而不用关心 “依赖从哪里来” + * 所有依赖关系都在di目录下集中配置,一目了然,后续维护时能快速找到所有依赖的创建逻辑。 + * + * 松耦合: + * 业务代码(ProductApplicationService)只依赖抽象接口(ProductRepository), + * 不依赖具体实现。如果未来需要改用其他数据来源(比如 WebSocket), + * 只需修改bindProductRepository的返回值,无需改动业务逻辑。 + * + * 易于测试: + * 测试时可以临时替换为模拟实现 + * productModule.bindProductRepository = () => new MockProductRepository(); + * 这样测试就可以脱离真实 API,使用预设的模拟数据。 + */ +export const product = { + + // 绑定 仓储抽象接口 到 HTTP具体实现 + bindProductRepository: (): ProductRepository => { + // return new MockProductRepository 直接从真实接口数据改为测试模拟数据 + return new HttpProductRepository; + }, + + // 创建应用服务实例 + createProductApplicationService: (): ProductApplicationService => { + return new ProductApplicationService( + product.bindProductRepository() + ); + } +} \ No newline at end of file diff --git a/src/domains/product/domain/entities/Product.ts b/src/domains/product/domain/entities/Product.ts new file mode 100644 index 0000000..236f464 --- /dev/null +++ b/src/domains/product/domain/entities/Product.ts @@ -0,0 +1,141 @@ +import { ErrorText } from "../enums/ErrorEnums" + +/** + * 商品实体 - 包含商品的核心属性和行为 + * 在DDD中,实体具有唯一标识和生命周期 + */ +export class Product { + private readonly _id: number; + private _name: string; + private _description: string; + private _price: number; + private _imageUrl: string; + private _stock: number; + private _categoryId: number; + + constructor( + id: number, + name: string, + description: string, + price: number, + imageUrl: string, + stock: number, + categoryId: number, + ) { + this._id = id; + this._name = name; + this._description = description; + this._price = price; + this._imageUrl = imageUrl; + this._stock = stock; + this._categoryId = categoryId; + } + + // 实体唯一标识 + get id(): number { + return this._id; + } + + public get name(): string { + return this._name; + } + public set name(value: string) { + this._name = value; + } + + public get description(): string { + return this._description; + } + public set description(value: string) { + this._description = value; + } + + + public get price(): number { + return this._price; + } + public set price(value: number) { + if (value < 0) { + throw new Error(ErrorText.PriceNotNegativein); + } + this._price = value; + } + + public get imageUrl(): string { + return this._imageUrl; + } + public set imageUrl(value: string) { + this._imageUrl = value; + } + + public get stock(): number { + return this._stock; + } + public set stock(value: number) { + if (value < 0) { + throw new Error(ErrorText.StockNotNegativein) + } + this._stock = value; + } + + public get categoryId(): number { + return this._categoryId; + } + public set categoryId(value: number) { + this._categoryId = value; + } + + /** + * 检查商品是否有库存 + */ + hasStock() { + return this._stock > 0 + } + + /** + * 减少商品库存 + * @param quantity 减少的数量 + */ + reduceStock(quantity: number): void { + if (quantity <= 0) { + throw new Error(ErrorText.StockIsGreaterThanZero) + } + + if (this._stock < quantity) { + throw new Error(ErrorText.LowStock) + } + + this._stock -= quantity; + } + + /** + * Class类转化为普通json数据 + */ + toDTO(): Record { + return { + id: this._id, + name: this._name, + description: this._description, + price: this._price, + imageUrl: this._imageUrl, + stock: this._stock, + categoryId: this._categoryId + } + } + + /** + * 从json数据创建Product类实例 + * 转化为领域实体 Product + */ + static fromDTO(data: Record): Product { + return new Product( + data.id, + data.name, + data.description, + data.price, + data.imageUrl, + data.stock, + data.categoryId, + ); + } +} \ No newline at end of file diff --git a/src/domains/product/domain/enums/ErrorEnums.ts b/src/domains/product/domain/enums/ErrorEnums.ts new file mode 100644 index 0000000..c766cc4 --- /dev/null +++ b/src/domains/product/domain/enums/ErrorEnums.ts @@ -0,0 +1,7 @@ +export enum ErrorText { + PriceNotNegativein = "商品 价格 不能为负数", + StockNotNegativein = "商品 库存 不能为负数", + StockIsGreaterThanZero = "减少的库存数量必须大于0", + LowStock = "库存不足", + IdNotNull = "商品Id不能为空" +} \ No newline at end of file diff --git a/src/domains/product/domain/events/README.md b/src/domains/product/domain/events/README.md new file mode 100644 index 0000000..abfa02f --- /dev/null +++ b/src/domains/product/domain/events/README.md @@ -0,0 +1 @@ +# 临时占位,上传空文件夹,保存文件结构用,后面删除 \ No newline at end of file diff --git a/src/domains/product/domain/type/ProductType.ts b/src/domains/product/domain/type/ProductType.ts new file mode 100644 index 0000000..8669e63 --- /dev/null +++ b/src/domains/product/domain/type/ProductType.ts @@ -0,0 +1,9 @@ +export interface ProductType { + id: number, + name: string, + description: string, + price: number, + imageUrl: string, + stock: number, + categoryId: number, +} \ No newline at end of file diff --git a/src/domains/product/domain/value-objects/README.md b/src/domains/product/domain/value-objects/README.md new file mode 100644 index 0000000..abfa02f --- /dev/null +++ b/src/domains/product/domain/value-objects/README.md @@ -0,0 +1 @@ +# 临时占位,上传空文件夹,保存文件结构用,后面删除 \ No newline at end of file diff --git a/src/domains/product/index.ts b/src/domains/product/index.ts new file mode 100644 index 0000000..6ac8f44 --- /dev/null +++ b/src/domains/product/index.ts @@ -0,0 +1,6 @@ +export * from './application/services/ProductApplicationService'; +export * from './domain/entities/Product'; +export * from './domain/enums/ErrorEnums'; +export * from './domain/type/ProductType'; +export * from './infr/api/HttpProductRepository'; +export * from './ports/repositories/ProductRepository'; \ No newline at end of file diff --git a/src/domains/product/infr/api/HttpProductRepository.ts b/src/domains/product/infr/api/HttpProductRepository.ts new file mode 100644 index 0000000..c7ee5fc --- /dev/null +++ b/src/domains/product/infr/api/HttpProductRepository.ts @@ -0,0 +1,27 @@ +import { Product } from "@domains/product/domain/entities/Product.ts"; +import { ProductType } from "@domains/product/domain/type/ProductType.ts"; +import { ProductRepository } from "@domains/product/ports/repositories/ProductRepository"; +import { http } from "shared/infra"; +import HttpConfig from "../config/HttpConfig"; + + +/** + * HTTP商品仓储实现 - 实现商品数据的HTTP访问 + * 这是基础设施层,负责具体的数据获取实现 + */ +export class HttpProductRepository implements ProductRepository { + + async findAll(): Promise> { + const result: Array = await http.get({ url: HttpConfig.apiUrlList.productsListUrl }); + const items = result.map((item) => Product.fromDTO(item)) + return items; + } + + async findById(id: number): Promise { + const result: ProductType = await http.get({ + url: HttpConfig.apiUrlList.productsInfoUrl, + data: { id } + }); + return Product.fromDTO(result); + } +} \ No newline at end of file diff --git a/src/domains/product/infr/config/HttpConfig.ts b/src/domains/product/infr/config/HttpConfig.ts new file mode 100644 index 0000000..3fd9fc2 --- /dev/null +++ b/src/domains/product/infr/config/HttpConfig.ts @@ -0,0 +1,11 @@ +interface apiUrlListType { + productsListUrl: string + productsInfoUrl: string +} + +export default class HttpConfig { + public static apiUrlList: apiUrlListType = { + productsListUrl: '/productsList', + productsInfoUrl: '/productsInfo', + } +} diff --git a/src/domains/product/ports/repositories/ProductRepository.ts b/src/domains/product/ports/repositories/ProductRepository.ts new file mode 100644 index 0000000..ee49c7f --- /dev/null +++ b/src/domains/product/ports/repositories/ProductRepository.ts @@ -0,0 +1,20 @@ +import { Product } from "../../domain/entities/Product" +import { ProductType } from "../../domain/type/ProductType" + +/** + * 商品仓储接口 - 定义商品数据访问的契约 + * 在DDD中,端口定义了领域层与外部世界的交互方式 + */ +export interface ProductRepository { + + /** + * 获取商品列表 + */ + findAll(): Promise>; + + /** + * 根据ID获取商品详情 + * @param id 商品ID + */ + findById(id: number): Promise +} \ No newline at end of file diff --git a/src/features/product/assets/README.md b/src/features/product/assets/README.md new file mode 100644 index 0000000..abfa02f --- /dev/null +++ b/src/features/product/assets/README.md @@ -0,0 +1 @@ +# 临时占位,上传空文件夹,保存文件结构用,后面删除 \ No newline at end of file diff --git a/src/features/product/components/README.md b/src/features/product/components/README.md new file mode 100644 index 0000000..abfa02f --- /dev/null +++ b/src/features/product/components/README.md @@ -0,0 +1 @@ +# 临时占位,上传空文件夹,保存文件结构用,后面删除 \ No newline at end of file diff --git a/src/features/product/composables/README.md b/src/features/product/composables/README.md new file mode 100644 index 0000000..abfa02f --- /dev/null +++ b/src/features/product/composables/README.md @@ -0,0 +1 @@ +# 临时占位,上传空文件夹,保存文件结构用,后面删除 \ No newline at end of file diff --git a/src/features/product/index.ts b/src/features/product/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/features/product/router/index.ts b/src/features/product/router/index.ts new file mode 100644 index 0000000..fd1b654 --- /dev/null +++ b/src/features/product/router/index.ts @@ -0,0 +1,16 @@ +import { RouteRecordRaw } from 'vue-router'; + +export const productRouter: Array = [ + { + path: '/Products', + name: 'ProductList', + component: () => import('../views/ProductList/ProductList.jsx'), + meta: { title: '商品列表' } + }, + { + path: '/ProductDetail', + name: 'ProductDetail', + component: () => import('../views/ProductDetail/ProductDetail.jsx'), + meta: { title: '商品详情' } + }, +] \ No newline at end of file diff --git a/src/features/product/views/ProductDetail/ProductDetail.module.less b/src/features/product/views/ProductDetail/ProductDetail.module.less new file mode 100644 index 0000000..739d26d --- /dev/null +++ b/src/features/product/views/ProductDetail/ProductDetail.module.less @@ -0,0 +1,5 @@ +.ProductDetail { + .title { + color: blue; + } +} \ No newline at end of file diff --git a/src/features/product/views/ProductDetail/ProductDetail.tsx b/src/features/product/views/ProductDetail/ProductDetail.tsx new file mode 100644 index 0000000..7fcbd63 --- /dev/null +++ b/src/features/product/views/ProductDetail/ProductDetail.tsx @@ -0,0 +1,62 @@ +import styles from './ProductDetail.module.less' + +import { product } from '@domains/product/di/productModule'; +import { ProductType } from '@domains/product/domain/type/ProductType'; +import { defineComponent, onMounted, reactive } from 'vue' +import { useRoute } from 'vue-router' + +interface storeType { + item: ProductType + id: number +} + +export default defineComponent({ + setup() { + const route = useRoute(); + const productService = product.createProductApplicationService(); + + const state = reactive({ + item: {} as ProductType, + id: 0 + }) + + onMounted(() => { + if (!route.query.id) { + throw new Error("缺少id参数"); + } + + state.id = Number(route.query.id) + console.log("id: ", state.id); + loadProductDetail() + }) + + const loadProductDetail = async () => { + state.item = await productService.getProductInfo(state.id); + console.log("state.item: ", state.item); + } + + return () => ( +
+

商品领域模块 - 商品详情页面

+
+

商品id:{ state.id }

+ { state.item.name } +
    + { + Object.entries(state.item).map(([ key, value ]) => +
  • { key }: { value }
  • + ) + } +
+
+ ) + } +}) + +// export default defineComponent({ +// setup() { +// return () => ( +//
商品详情
+// ) +// } +// }) \ No newline at end of file diff --git a/src/features/product/views/ProductList/ProductList.module.less b/src/features/product/views/ProductList/ProductList.module.less new file mode 100644 index 0000000..afc4c2a --- /dev/null +++ b/src/features/product/views/ProductList/ProductList.module.less @@ -0,0 +1,5 @@ +.ProductList { + .test { + color: var(--theme-color); + } +} diff --git a/src/features/product/views/ProductList/ProductList.tsx b/src/features/product/views/ProductList/ProductList.tsx new file mode 100644 index 0000000..1c1c862 --- /dev/null +++ b/src/features/product/views/ProductList/ProductList.tsx @@ -0,0 +1,79 @@ +import styles from './ProductList.module.less' + +import { defineComponent, onMounted, reactive } from 'vue' +import { useRouter } from 'vue-router'; +import { product } from '@domains/product/di/productModule'; +import { ProductType } from '@domains/product/domain/type/ProductType'; +import { ElCard, ElIcon, Icons } from "shared/element-plus"; + +interface storeType { + list: Array +} + +export default defineComponent({ + setup() { + + const router = useRouter(); + const productService = product.createProductApplicationService(); + + const state = reactive({ + list: [] + }) + + + onMounted(() => { + loadProductList() + }) + + const loadProductList = async () => { + state.list = await productService.getProductList(); + console.log("state.list: ", state.list); + } + + const ElCardHeader = () => { + return ( +
+ + + + Card 头部 +
+ ) + } + + const ElCardFooter = () => { + return
Footer 底部
+ } + + return () => ( +
+

商品领域模块 - 商品列表页面3

+
+

从Deno 后端 加载的数据,点击进详情

+ + { { + header: () => ElCardHeader(), + footer: () => ElCardFooter(), + default: () => + state.list.map(item => +

{ + router.push({ name: 'ProductDetail', query: { id: item.id } }); + } }> + { item.id } | { item.name } | ¥{ item.price } +

+ ) + } } +
+ +
+ ) + } +}) + +// export default defineComponent({ +// setup() { +// return () => ( +//
商品列表
+// ) +// } +// }) \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..dcbab81 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,12 @@ +// import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App' + + +createApp(App) + .use(createPinia()) + .mount('#app') + diff --git a/src/shared/types/env.d.ts b/src/shared/types/env.d.ts new file mode 100644 index 0000000..c7077e0 --- /dev/null +++ b/src/shared/types/env.d.ts @@ -0,0 +1,4 @@ +declare module '*.module.less' { + const classes: { [key: string]: string } + export default classes +} diff --git a/src/shared/types/shared.d.ts b/src/shared/types/shared.d.ts new file mode 100644 index 0000000..6a93e75 --- /dev/null +++ b/src/shared/types/shared.d.ts @@ -0,0 +1,29 @@ +/// + +declare module 'shared/infra' { + export const http: any; +} + +declare module 'shared/utils' { + export const UrlCheckUtils: any; +} + +declare module 'shared/element-plus' { + import * as ElementPlus from 'element-plus'; + import * as ElementPlusIcons from '@element-plus/icons-vue'; + import type { App } from 'vue'; + export * from 'element-plus'; + export import Icons = ElementPlusIcons; + + export function init(app: App): void; + + const defaultExport: typeof ElementPlus & { + Icons: typeof ElementPlusIcons; + init: typeof init; + }; + export default defaultExport; +} + +declare module 'shared/normalize' { + export const init: () => void; +} \ No newline at end of file diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..2102b28 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,33 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": [ + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*", + "src/**/*.tsx", + "src/**/*.vue" + ], + "exclude": [ + "src/**/__tests__/*" + ], + "compilerOptions": { + "verbatimModuleSyntax": false, + "jsx": "preserve", + "jsxImportSource": "vue", + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "paths": { + "@/*": [ + "./src/app/*" + ], + "@shared/*": [ + "./src/shared/*" + ], + "@features/*": [ + "./src/features/*" + ], + "@domains/*": [ + "./src/domains/*" + ] + } + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..a83dfc9 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*", + "eslint.config.*" + ], + "compilerOptions": { + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..7e36fc4 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,66 @@ +import { defineConfig, loadEnv } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx' +import vueDevTools from 'vite-plugin-vue-devtools' +import federation from 'vite-federation'; +import { fileURLToPath, URL } from "node:url"; +import { visualizer } from 'rollup-plugin-visualizer'; +import { reg, init } from 'vite-plugin-nacos'; + +export default defineConfig(async ({ mode }) => { + const env = loadEnv(mode, process.cwd()); + const { VITE_MODEL_SHARED_URL } = await init(env) + + // console.log("VITE_MODEL_SHARED_URL: ", VITE_MODEL_SHARED_URL); + + return { + plugins: [ + reg(), + + federation({ + name: env.VITE_SERVER_NAME, + remotes: { + shared: `${VITE_MODEL_SHARED_URL}/${env.VITE_MODEL_SHARED_NAME}/assets/remoteEntry.js` + }, + exposes: { // 暴露给主应用的资源(按功能分组) + './ProductDomain': './src/domains/product/index.ts', // 领域层(实体、服务、接口等) + './ProductRouter': './src/features/product/router/index.ts' // 商品路由 + }, + shared: { + vue: { import: false, generate: false, requiredVersion: '^3.5.18' }, + 'vue-router': { import: false, generate: false, requiredVersion: '^4.0.6' }, + pinia: { import: false, generate: false, requiredVersion: '^3.0.3' }, + } + }), + vue(), + vueJsx(), + vueDevTools(), + visualizer({ + title: "商品模块依赖分析", + filename: 'dist/stats.html', // 分析文件输出路径 + open: false, // 构建完成后自动打开 + gzipSize: true, // 显示gzip后的大小 + brotliSize: true, // 显示brotli后的大小 + }) + ], + build: { + target: 'esnext', + cssCodeSplit: true, + rollupOptions: { + // 关键配置:告诉 Rollup 不要处理模块联邦的导入 + external: ['shared/normalize'], + output: { + minifyInternalExports: false + } + } + }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src/', import.meta.url)), + '@shared': fileURLToPath(new URL('./src/shared/', import.meta.url)), + '@features': fileURLToPath(new URL('./src/features/', import.meta.url)), + '@domains': fileURLToPath(new URL('./src/domains/', import.meta.url)) + }, + }, + } +}); \ No newline at end of file