diff --git a/README.md b/README.md index 087acfe..ad82767 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,65 @@ # points-mall -积分商城-供应商模块-订单操作模块 +积分商城供应商项目,对接 zhgh 工会平台,包含商城 H5、供应商管理后台及业务服务。 -## 页面与接口 +## 项目组成 + +| 目录 | 用途 | 技术栈 | +| --- | --- | --- | +| `supplied-h5` | 商品浏览、购物车、下单支付、订单与售后、商家处理台 | Vue 3、Vant 3、Pinia、Vue Router 4、Vue CLI | +| `supplied-admin` | 商品管理、订单管理、售后处理、订单对账 | Vue 3、Element Plus、Pinia、Vue Router 4、Vite | +| `supplied-service` | 商城接口、管理端接口、工会平台对接、文件处理 | Koa、TypeScript、Prisma、MySQL、Redis、MinIO | + +H5 和管理端的 Vue 版本声明均为 `^3.5.13`,H5 的 Vant 版本声明为 `^3.6.16`。 + +## 主要功能 + +- 商城 H5:商品与规格选择、购物车、地址管理、下单支付、订单查询及售后申请。 +- 管理后台:账号登录、商品维护、订单筛选与分页、确认发货、重新推送拆单、售后审核与处理、订单对账。 +- 平台对接:供应商授权、订单事件推送、对账及发票相关接口。 +- 调试日志:查看供应商后端与 zhgh 之间的请求记录。 + +## 本地访问入口 + +以下为默认开发地址,实际地址以端口和环境配置为准。 + +| 入口 | 地址 | +| --- | --- | +| 管理端登录 | `http://localhost:5173/login` | +| 管理端订单列表 | `http://localhost:5173/orders/list` | +| 商城 H5 | `http://localhost:3001/` | +| 商城 API | `http://localhost:8888/api` | +| 管理端 API | `http://localhost:8888/api/admin` | + +### 商家处理与日志 - 商家处理台:`http://localhost:3001/#/joyful-selection/merchant` - 供应商日志页面:`http://localhost:3001/#/joyful-selection/supplier-logs` - 供应商日志接口:`GET http://localhost:8888/api/supplier-logs` - 日志内容包含:当前后端接收请求、向zhgh发送请求、接收zhgh请求。 + + +## 管理端登录 + +当前本地开发数据库已初始化以下账号;密码由初始化脚本生成并单独交付,不在文档中保存。 + +| 项目 | 内容 | +| --- | --- | +| 账号 | `admin` | +| 登录后进入订单列表 | `http://localhost:5173/login?redirect=/orders/list` | + +- 登录账号存储在 `supplied_user`,密码使用随机盐和 scrypt 哈希保存,不保存明文密码。 +- 管理端使用 Bearer Token,登录有效期为 8 小时;同一账号重新登录会替换旧 Token。 +- `/api/admin/*` 除登录接口外均校验登录状态;退出登录会使当前 Token 失效。 +- 同一启用账号连续输错密码 5 次后锁定 15 分钟。 + +## 数据库与配置 + +- 管理账号表:`supplied_user`。 +- 购物车表:`supplied_cart_item`;保留业务用户 `userId`,不关联后台管理员账号。 +- 原 `user` 空表已移除,购物车表名统一使用 `supplied_cart_item`。 +- 后端配置位于 `supplied-service/.env`,字段参考 `.env.example`。 +- H5 使用 `VUE_APP_SUPPLIED_API_BASE` 指定后端地址,使用 `VUE_APP_SUPPLIER_IDENTIFICATION` 指定供应商标识。 +- 管理端使用 `VITE_SUPPLIED_ADMIN_API_BASE` 指定管理接口地址。 + +后端目录、接口及初始化脚本说明见 [supplied-service/README.md](supplied-service/README.md)。 \ No newline at end of file diff --git a/supplied-admin/src/api/admin.ts b/supplied-admin/src/api/admin.ts index ac112ad..61e93e6 100644 --- a/supplied-admin/src/api/admin.ts +++ b/supplied-admin/src/api/admin.ts @@ -1,14 +1,23 @@ +import { clearAdminSession, readAdminSession } from '@/utils/auth' + const API_BASE = import.meta.env.VITE_SUPPLIED_ADMIN_API_BASE || 'http://127.0.0.1:8888/api/admin' const normalizeBase = (base: string) => base.replace(/\/$/, '') export const postAdmin = async (name: string, body: Record): Promise => { + const token = readAdminSession()?.token const response = await fetch(`${normalizeBase(API_BASE)}/${name}`, { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) }, body: JSON.stringify(body) }) const payload = await response.json().catch(() => ({})) + if (response.status === 401 && name !== 'login') { + clearAdminSession() + if (name !== 'admin-session' && window.location.pathname !== '/login') { + window.location.replace(`/login?redirect=${encodeURIComponent(window.location.pathname + window.location.search)}`) + } + } if (!response.ok || payload.success === false) { throw new Error(payload.error?.message || payload.msg || '请求失败') } diff --git a/supplied-admin/src/components/MerchantAfterSaleTable.vue b/supplied-admin/src/components/MerchantAfterSaleTable.vue index 5c942e6..001c6c8 100644 --- a/supplied-admin/src/components/MerchantAfterSaleTable.vue +++ b/supplied-admin/src/components/MerchantAfterSaleTable.vue @@ -1,5 +1,5 @@ diff --git a/supplied-admin/src/router/index.ts b/supplied-admin/src/router/index.ts index 51b3f54..8505fa9 100644 --- a/supplied-admin/src/router/index.ts +++ b/supplied-admin/src/router/index.ts @@ -1,7 +1,10 @@ import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router' import AdminLayout from '@/layouts/AdminLayout.vue' +import { ElMessage } from 'element-plus' +import { postAdmin } from '@/api/admin' +import { clearAdminSession, readAdminSession } from '@/utils/auth' -const routes: RouteRecordRaw[] = [{ path: '/', component: AdminLayout, redirect: '/reconciliation', children: [ +const routes: RouteRecordRaw[] = [{ path: '/login', name: 'Login', component: () => import('@/views/login/index.vue'), meta: { title: '登录' } }, { path: '/', component: AdminLayout, redirect: '/reconciliation', children: [ { path: 'reconciliation', name: 'Reconciliation', component: () => import('@/views/reconciliation/index.vue'), meta: { title: '订单对账' } }, { path: 'orders', redirect: '/orders/list' }, { path: 'orders/list', name: 'Orders', component: () => import('@/views/orders/index.vue'), meta: { title: '订单列表' } }, @@ -11,4 +14,20 @@ const routes: RouteRecordRaw[] = [{ path: '/', component: AdminLayout, redirect: { path: 'products', name: 'Products', component: () => import('@/views/products/index.vue'), meta: { title: '商品管理' } } ] }] -export default createRouter({ history: createWebHistory(), routes }) +const router = createRouter({ history: createWebHistory(), routes }) + +router.beforeEach(async to => { + if (to.name === 'Login') return true + if (readAdminSession()) { + try { + await postAdmin('admin-session', {}) + return true + } catch (error) { + clearAdminSession() + ElMessage.error(error instanceof Error ? error.message : '登录状态校验失败,请重新登录') + } + } + return { name: 'Login', query: { redirect: to.fullPath } } +}) + +export default router diff --git a/supplied-admin/src/styles/index.scss b/supplied-admin/src/styles/index.scss index d83ee70..49f57e2 100644 --- a/supplied-admin/src/styles/index.scss +++ b/supplied-admin/src/styles/index.scss @@ -1 +1,97 @@ -html, body, #app { min-width: 1180px; min-height: 100%; margin: 0; } body { color: #303133; font-family: "Microsoft YaHei", Arial, sans-serif; }.page-card { min-height: calc(100vh - 96px); padding: 24px; border-radius: 8px; background: #fff; }.page-title { display: flex; align-items: center; justify-content: space-between; margin-bottom: 26px; }.page-title h2 { margin: 0 0 8px; font-size: 20px; }.page-title p { margin: 0; color: #909399; font-size: 14px; }.query-form { padding: 18px 18px 2px; margin-bottom: 20px; border-radius: 6px; background: #f8fafc; } +:root { + --el-color-primary: #2463d4; + --el-color-primary-light-3: #668fdf; + --el-color-primary-light-5: #91b1ea; + --el-color-primary-light-7: #bed0f2; + --el-color-primary-light-8: #d3e0f7; + --el-color-primary-light-9: #edf3fd; + --el-color-primary-dark-2: #1d4faa; + --el-border-radius-base: 7px; + --el-border-color: #dce3ec; + --el-border-color-light: #e9eef5; + --el-text-color-primary: #202e45; + --el-text-color-regular: #526078; + --el-text-color-secondary: #78859a; + --el-font-family: "Microsoft YaHei", "PingFang SC", Arial, sans-serif; +} + +html, body, #app { min-width: 360px; min-height: 100%; margin: 0; } +body { color: var(--el-text-color-primary); font-family: var(--el-font-family); background: #f3f5f9; -webkit-font-smoothing: antialiased; } +*, *::before, *::after { box-sizing: border-box; } +button, input, textarea { font: inherit; } +:focus-visible { outline: 2px solid #2463d4; outline-offset: 3px; } + +.page-card { + min-width: 0; + min-height: calc(100vh - 112px); + padding: 28px; + border: 1px solid #e5eaf2; + border-radius: 14px; + background: #fff; + box-shadow: 0 3px 16px rgba(30, 50, 85, .035); +} +.page-title { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 16px; margin-bottom: 24px; } +.page-title h2 { margin: 0 0 8px; color: #202e45; font-size: 22px; font-weight: 600; letter-spacing: .5px; } +.page-title p { margin: 0; color: #78859a; font-size: 13px; line-height: 1.7; } +.query-form.el-form--inline { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 16px 20px; padding: 20px; margin-bottom: 24px; border: 1px solid #e9eef5; border-radius: 10px; background: #f8fafc; } +.query-form.el-form--inline .el-form-item { display: flex; flex-direction: column; align-items: stretch; margin: 0; } +.query-form .el-form-item__label { justify-content: flex-start; height: auto; padding: 0 0 8px; color: #526078; font-size: 13px; line-height: 18px; } +.query-form .el-form-item__content { min-height: 36px; } +.query-form .el-input, .query-form .el-select { width: 208px; max-width: 100%; } +.query-form .el-button { min-width: 76px; height: 36px; } +.el-input__wrapper, .el-select__wrapper { min-height: 36px; } +.el-textarea__inner { padding: 10px 12px; line-height: 1.6; } +.page-title > .el-button { height: 36px; padding: 0 18px; } +.el-button { font-weight: 500; } +.el-button:not(.is-link):not(.is-text) { border-radius: 7px; } + +.page-card .el-table { + --el-table-border-color: #e9eef5; + --el-table-header-bg-color: #f7f9fc; + --el-table-header-text-color: #526078; + --el-table-row-hover-bg-color: #f3f7ff; + overflow: hidden; + border-radius: 9px; + color: #3f4d63; + font-size: 13px; +} +.page-card .el-table th.el-table__cell { padding: 13px 0; font-size: 12px; font-weight: 600; } +.page-card .el-table td.el-table__cell { padding: 15px 0; } +.page-card .el-table .cell { padding-right: 16px; padding-left: 16px; line-height: 22px; } +.page-card .el-table .el-button.is-link { font-size: 13px; } +.page-card .el-table .el-table__empty-block { min-height: 240px; } +.page-card .el-table .el-table__empty-text { width: 100%; line-height: normal; } +.page-card .el-empty { padding: 36px 0; } +.el-empty__description p { color: #8793a5; font-size: 13px; } +.page-card .el-tag { height: 25px; padding: 0 9px; border-color: transparent; border-radius: 5px; font-size: 12px; font-weight: 500; } +.page-card .el-pagination { justify-content: flex-end; flex-wrap: wrap; gap: 8px; padding-top: 20px; margin-top: 20px; border-top: 1px solid #edf0f5; font-variant-numeric: tabular-nums; } +.page-card .el-pagination .el-pager li { border-radius: 6px; } +.page-card .el-pagination .el-pager li.is-active { color: #fff; background: var(--el-color-primary); } + +.el-dialog { max-width: calc(100vw - 32px); padding: 0; overflow: hidden; border-radius: 14px; box-shadow: 0 24px 80px rgba(15, 30, 55, .18); } +.el-dialog__header { padding: 22px 52px 20px 24px; margin: 0; border-bottom: 1px solid #edf0f5; } +.el-dialog__title { color: #202e45; font-size: 17px; font-weight: 600; } +.el-dialog__headerbtn { top: 9px; right: 8px; } +.el-dialog__body { max-height: 65vh; padding: 24px; overflow-y: auto; } +.el-dialog__footer { padding: 16px 24px; border-top: 1px solid #edf0f5; background: #fafbfd; } +.el-dialog .el-form-item { margin-bottom: 22px; } +.el-dialog .el-form-item:last-child { margin-bottom: 0; } +.el-dialog .el-select, .el-dialog .el-input-number { width: 100%; } +.el-dialog__footer .el-button { min-width: 80px; height: 36px; } +.el-message-box { max-width: calc(100vw - 32px); padding: 20px; border-radius: 12px; } + +@media (max-width: 1200px) { + .page-card { padding: 22px; } + .query-form .el-input, .query-form .el-select { width: 180px; } +} +@media (max-width: 767px) { + .page-card { min-height: calc(100vh - 88px); padding: 16px; border-radius: 10px; } + .page-title h2 { font-size: 19px; } + .query-form.el-form--inline { gap: 14px; padding: 14px; } + .query-form.el-form--inline .el-form-item { width: 100%; } + .query-form .el-input, .query-form .el-select { width: 100% !important; } + .el-dialog__body { padding: 18px; } +} +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { scroll-behavior: auto !important; transition-duration: 0s !important; animation-duration: 0s !important; } +} diff --git a/supplied-admin/src/utils/auth.ts b/supplied-admin/src/utils/auth.ts new file mode 100644 index 0000000..6a00cfe --- /dev/null +++ b/supplied-admin/src/utils/auth.ts @@ -0,0 +1,14 @@ +export type AdminUser = { id: number; username: string; nickname: string } +export type AdminSession = { token: string; expiresAt: string; user: AdminUser } +const STORAGE_KEY = 'supplied-admin-session' + +export const clearAdminSession = () => sessionStorage.removeItem(STORAGE_KEY) +export const saveAdminSession = (session: AdminSession) => sessionStorage.setItem(STORAGE_KEY, JSON.stringify(session)) +export const readAdminSession = (): AdminSession | null => { + try { + const session = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || 'null') + if (session?.token && session?.user && Date.parse(session.expiresAt) > Date.now()) return session + } catch { /* 忽略已损坏的本地登录信息。 */ } + clearAdminSession() + return null +} diff --git a/supplied-admin/src/views/login/index.vue b/supplied-admin/src/views/login/index.vue new file mode 100644 index 0000000..c172cc3 --- /dev/null +++ b/supplied-admin/src/views/login/index.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/supplied-admin/src/views/orders/index.vue b/supplied-admin/src/views/orders/index.vue index 12b0a51..538d4c4 100644 --- a/supplied-admin/src/views/orders/index.vue +++ b/supplied-admin/src/views/orders/index.vue @@ -1,21 +1,32 @@ + + diff --git a/supplied-admin/src/views/products/index.vue b/supplied-admin/src/views/products/index.vue index 7fd10f5..6d52074 100644 --- a/supplied-admin/src/views/products/index.vue +++ b/supplied-admin/src/views/products/index.vue @@ -2,8 +2,8 @@

商品管理

管理供应商商品的展示、库存和上下架状态。

新增商品
查询重置 - - + +
diff --git a/supplied-admin/src/views/reconciliation/index.vue b/supplied-admin/src/views/reconciliation/index.vue index 9805973..65bd791 100644 --- a/supplied-admin/src/views/reconciliation/index.vue +++ b/supplied-admin/src/views/reconciliation/index.vue @@ -18,8 +18,8 @@ - - + + {{ editing?.orderId }} diff --git a/supplied-h5/package-lock.json b/supplied-h5/package-lock.json index 6a1a02e..c14f430 100644 --- a/supplied-h5/package-lock.json +++ b/supplied-h5/package-lock.json @@ -11,16 +11,16 @@ "@vant/area-data": "^1.5.2", "core-js": "^3.37.1", "pinia": "^2.3.1", - "vant": "^2.13.9", - "vue": "^2.7.16", - "vue-router": "^3.6.5" + "vant": "^3.6.16", + "vue": "^3.5.13", + "vue-router": "^4.5.0" }, "devDependencies": { "@vue/cli-plugin-babel": "~5.0.8", "@vue/cli-service": "~5.0.8", + "@vue/compiler-sfc": "^3.5.13", "less": "^4.2.0", - "less-loader": "^10.2.0", - "vue-template-compiler": "^2.7.16" + "less-loader": "^10.2.0" } }, "node_modules/@achrinza/node-ipc": { @@ -337,10 +337,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.7", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.29.7" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -1446,6 +1448,7 @@ }, "node_modules/@babel/runtime": { "version": "7.29.7", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1482,7 +1485,9 @@ } }, "node_modules/@babel/types": { - "version": "7.29.7", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.29.7", @@ -1550,7 +1555,6 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -1859,15 +1863,27 @@ "license": "MIT" }, "node_modules/@vant/icons": { - "version": "3.0.2", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vant/icons/-/icons-1.8.0.tgz", + "integrity": "sha512-sKfEUo2/CkQFuERxvkuF6mGQZDKu3IQdj5rV9Fm0weJXtchDSSQ+zt8qPCNUEhh9Y8shy5PzxbvAfOOkCwlCXg==", "license": "MIT" }, "node_modules/@vant/popperjs": { "version": "1.3.0", "license": "MIT" }, + "node_modules/@vant/use": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vant/use/-/use-1.6.0.tgz", + "integrity": "sha512-PHHxeAASgiOpSmMjceweIrv2AxDZIkWXyaczksMoWvKV2YAYEhoizRuk/xFnKF+emUIi46TsQ+rvlm/t2BBCfA==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.0.0" + } + }, "node_modules/@vue/babel-helper-vue-jsx-merge-props": { "version": "1.4.0", + "dev": true, "license": "MIT" }, "node_modules/@vue/babel-helper-vue-transform-on": { @@ -2277,49 +2293,53 @@ "license": "ISC" }, "node_modules/@vue/compiler-core": { - "version": "3.5.39", - "dev": true, + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.42.tgz", + "integrity": "sha512-2Ye1ilMtKXxl8qZUrQ5j0CdgenFp/HFQmta6rfRyfEsTG69L6Wk+tWuNoHYHMx9E8tF2Slvdg1FuwDvAXdy1LQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.7", - "@vue/shared": "3.5.39", + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.42", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.39", - "dev": true, + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.42.tgz", + "integrity": "sha512-qbhQZEFmycr+ni/qyuccS4sucNN7VAbDfbkvNxWOX2VfgFm90MNs3/UhRNKoPMEIVn0F8gdlYjLPvqxHwHeQOA==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.39", - "@vue/shared": "3.5.39" + "@vue/compiler-core": "3.5.42", + "@vue/shared": "3.5.42" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.39", - "dev": true, + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.42.tgz", + "integrity": "sha512-fkCAFB4okcAANGMThboWnScp/gzWjU0ZSkVnjTIiplmMDq2uq0tIB3j+xVu4rhv5rvOgBySCysudmbMd6xRRqw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.7", - "@vue/compiler-core": "3.5.39", - "@vue/compiler-dom": "3.5.39", - "@vue/compiler-ssr": "3.5.39", - "@vue/shared": "3.5.39", + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.42", + "@vue/compiler-dom": "3.5.42", + "@vue/compiler-ssr": "3.5.42", + "@vue/shared": "3.5.42", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", - "postcss": "^8.5.15", + "postcss": "^8.5.19", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.39", - "dev": true, + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.42.tgz", + "integrity": "sha512-xmLk3wLkbizPAiLyomjgFFosf2ys9b5Ghb+oh/k2tnvipNz8OFrQOiTcWCzyK7MpBp9KkyGtfvgfLUivbmuGYA==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.39", - "@vue/shared": "3.5.39" + "@vue/compiler-dom": "3.5.42", + "@vue/shared": "3.5.42" } }, "node_modules/@vue/component-compiler-utils": { @@ -2386,9 +2406,52 @@ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "license": "MIT" }, + "node_modules/@vue/reactivity": { + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.42.tgz", + "integrity": "sha512-TzNNfKpb7hDxbQltwAut8VDQA5YP+BuRlxntHUuRjyKwlMvmAPbs3unhCvieijifY6vFfVBwsS7wG/C7uq+bEQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.42.tgz", + "integrity": "sha512-9uACtuHs7vJGkm5Bp3xu4xRDLFTIYy5DgxpToVjqGIAhAEKwQfsaLvKINhM6nFVp6bZPRFGdDqd1g52MqKsotA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.42.tgz", + "integrity": "sha512-rsCmhiWLaRxGltLwhlCWyYkFn7WAbKRh0q17eZ1A6Dq6eqc2ACQ61IIryxz0LrsvCzHSilLA9JHovVwM8CNE2g==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.42", + "@vue/runtime-core": "3.5.42", + "@vue/shared": "3.5.42", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.42.tgz", + "integrity": "sha512-2++5dUyYS4gvo7xQXSECUDhB7TS0aOl5SeVfC5qSq1Jgfhjvegw1zqhwTIR3imZ+QYPJQw9gfcFvXGAjGZ7ajQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.42", + "@vue/runtime-dom": "3.5.42", + "@vue/shared": "3.5.42" + } + }, "node_modules/@vue/shared": { - "version": "3.5.39", - "dev": true, + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.42.tgz", + "integrity": "sha512-2rPxex1jQf4jvl9MOHl6YaXCPcrNqz/FstMOEh3QWY+/OME9nQTvl9WYeCwhW7AFjaR0SnngZGlp/wkR6rkI6g==", "license": "MIT" }, "node_modules/@vue/vue-loader-v15": { @@ -3981,11 +4044,8 @@ }, "node_modules/csstype": { "version": "3.2.3", - "license": "MIT" - }, - "node_modules/de-indent": { - "version": "1.0.2", - "dev": true, + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/debounce": { @@ -4400,7 +4460,8 @@ }, "node_modules/entities": { "version": "7.0.1", - "dev": true, + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -4531,7 +4592,8 @@ }, "node_modules/estree-walker": { "version": "2.0.2", - "dev": true, + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "license": "MIT" }, "node_modules/esutils": { @@ -6048,7 +6110,6 @@ }, "node_modules/magic-string": { "version": "0.30.21", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -6452,7 +6513,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.16", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "funding": [ { "type": "github", @@ -7020,7 +7083,9 @@ } }, "node_modules/postcss": { - "version": "8.5.18", + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", "funding": [ { "type": "opencollective", @@ -7037,7 +7102,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -7553,6 +7618,7 @@ }, "node_modules/prettier": { "version": "2.8.8", + "dev": true, "license": "MIT", "optional": true, "bin": { @@ -8397,6 +8463,7 @@ }, "node_modules/source-map": { "version": "0.6.1", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -9025,19 +9092,17 @@ } }, "node_modules/vant": { - "version": "2.13.9", - "resolved": "https://registry.npmmirror.com/vant/-/vant-2.13.9.tgz", - "integrity": "sha512-AIDYTUKOlqEolrTs18vZanLX9Mq6IftzwOnbozaNFmx9+xMrCeJIqRKefbGUPZ7irQvO6t397+VwRXqCSHnedQ==", + "version": "3.6.16", + "resolved": "https://registry.npmjs.org/vant/-/vant-3.6.16.tgz", + "integrity": "sha512-9pZao0NEeZQ0ZEb6N7SZxtqcdTp24o8IizhZS1G+FtStlXeKOFzCl+Nf1pIWRneQ9Kn+K+mNrfi2eiIZjVVppw==", "license": "MIT", "dependencies": { - "@babel/runtime": "7.x", - "@vant/icons": "^3.0.2", - "@vant/popperjs": "^1.1.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", - "vue-lazyload": "1.2.3" + "@vant/icons": "^1.8.0", + "@vant/popperjs": "^1.2.1", + "@vant/use": "^1.4.2" }, "peerDependencies": { - "vue": ">= 2.6.0" + "vue": "^3.0.0" } }, "node_modules/vary": { @@ -9049,11 +9114,24 @@ } }, "node_modules/vue": { - "version": "2.7.16", + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.42.tgz", + "integrity": "sha512-4RyHQTbQvOPs3MfvUO1Sg0YRrKNnA0mAVtvpd12Tg1fKDN7OHBUl1IqSn8zGJjK9nI3NkNp8cgTpVrSZC5TTcA==", "license": "MIT", "dependencies": { - "@vue/compiler-sfc": "2.7.16", - "csstype": "^3.1.0" + "@vue/compiler-dom": "3.5.42", + "@vue/compiler-sfc": "3.5.42", + "@vue/runtime-dom": "3.5.42", + "@vue/server-renderer": "3.5.42", + "@vue/shared": "3.5.42" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/vue-hot-reload-api": { @@ -9061,10 +9139,6 @@ "dev": true, "license": "MIT" }, - "node_modules/vue-lazyload": { - "version": "1.2.3", - "license": "MIT" - }, "node_modules/vue-loader": { "version": "17.4.2", "dev": true, @@ -9102,10 +9176,19 @@ } }, "node_modules/vue-router": { - "version": "3.6.5", - "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-3.6.5.tgz", - "integrity": "sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==", - "license": "MIT" + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } }, "node_modules/vue-style-loader": { "version": "4.1.3", @@ -9121,31 +9204,11 @@ "dev": true, "license": "MIT" }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "dev": true, - "license": "MIT", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, "node_modules/vue-template-es2015-compiler": { "version": "1.9.1", "dev": true, "license": "MIT" }, - "node_modules/vue/node_modules/@vue/compiler-sfc": { - "version": "2.7.16", - "dependencies": { - "@babel/parser": "^7.23.5", - "postcss": "^8.4.14", - "source-map": "^0.6.1" - }, - "optionalDependencies": { - "prettier": "^1.18.2 || ^2.0.0" - } - }, "node_modules/watchpack": { "version": "2.5.2", "dev": true, diff --git a/supplied-h5/package.json b/supplied-h5/package.json index 74b1e31..d893f2f 100644 --- a/supplied-h5/package.json +++ b/supplied-h5/package.json @@ -10,15 +10,15 @@ "@vant/area-data": "^1.5.2", "core-js": "^3.37.1", "pinia": "^2.3.1", - "vant": "^2.13.9", - "vue": "^2.7.16", - "vue-router": "^3.6.5" + "vant": "^3.6.16", + "vue": "^3.5.13", + "vue-router": "^4.5.0" }, "devDependencies": { "@vue/cli-plugin-babel": "~5.0.8", "@vue/cli-service": "~5.0.8", "less": "^4.2.0", "less-loader": "^10.2.0", - "vue-template-compiler": "^2.7.16" + "@vue/compiler-sfc": "^3.5.13" } } diff --git a/supplied-h5/src/components/SupplierShop.vue b/supplied-h5/src/components/SupplierShop.vue index b62f4a6..005caa2 100644 --- a/supplied-h5/src/components/SupplierShop.vue +++ b/supplied-h5/src/components/SupplierShop.vue @@ -14,7 +14,7 @@ - + @@ -44,7 +44,7 @@ 已选 {{ totalCount }} 件 - +

确认订单

@@ -66,7 +66,7 @@
- +

订单提交成功

订单号:{{ submittedOrderId }}

diff --git a/supplied-h5/src/main.js b/supplied-h5/src/main.js index 213e3e0..22d475a 100644 --- a/supplied-h5/src/main.js +++ b/supplied-h5/src/main.js @@ -1,20 +1,11 @@ -import Vue from 'vue' +import { createApp } from 'vue' import Vant from 'vant' -import { Skeleton } from 'vant' -import { createPinia, PiniaVuePlugin } from 'pinia' +import { createPinia } from 'pinia' import 'vant/lib/index.css' import App from './App.vue' import router from './router' -Vue.use(Vant) -Vue.use(Skeleton) -Vue.use(PiniaVuePlugin) -Vue.config.productionTip = false const pinia = createPinia() -new Vue({ - router, - pinia, - render: h => h(App) -}).$mount('#app') +createApp(App).use(pinia).use(router).use(Vant).mount('#app') diff --git a/supplied-h5/src/router/index.js b/supplied-h5/src/router/index.js index c075d1a..b0cb84a 100644 --- a/supplied-h5/src/router/index.js +++ b/supplied-h5/src/router/index.js @@ -1,5 +1,4 @@ -import Vue from 'vue' -import Router from 'vue-router' +import { createRouter, createWebHashHistory } from 'vue-router' import SupplierHome from '@/view/index.vue' import JoyfulSelectionLayout from '@/view/joyful-selection/layout.vue' import JoyfulSelectionHome from '@/view/joyful-selection/index.vue' @@ -29,16 +28,15 @@ import HappyShopping from '@/view/happy-shopping/index.vue' import FreshFruit from '@/view/fresh-fruit/index.vue' import CuteSelection from '@/view/cute-selection/index.vue' -Vue.use(Router) - -export default new Router({ +export default createRouter({ + history: createWebHashHistory(), routes: [ { path: '/', component: SupplierHome }, { path: '/joyful-selection', component: JoyfulSelectionLayout, children: [ - { path: '', redirect: 'home' }, + { path: '', redirect: '/joyful-selection/home' }, { path: 'home', component: JoyfulSelectionHome }, { path: 'products', component: JoyfulSelectionProductList }, { path: 'product-detail', component: JoyfulSelectionProductDetail }, diff --git a/supplied-h5/src/store/user.js b/supplied-h5/src/store/user.js index 1d2137c..24f683c 100644 --- a/supplied-h5/src/store/user.js +++ b/supplied-h5/src/store/user.js @@ -20,6 +20,7 @@ const saveUser = data => { export const useUserStore = defineStore('joyfulSelectionUser', { state: () => ({ userId: '', + nickname: '', supplierIdentification: '', supplierId: '', supplierName: '', @@ -34,6 +35,7 @@ export const useUserStore = defineStore('joyfulSelectionUser', { loadUser() { const data = readUser() this.userId = data.userId || '' + this.nickname = data.nickname || '' const supplierIdentification = DEFAULT_SUPPLIER_IDENTIFICATION || data.supplierIdentification || '' const supplierChanged = Boolean(data.supplierIdentification && supplierIdentification !== data.supplierIdentification) @@ -46,6 +48,7 @@ export const useUserStore = defineStore('joyfulSelectionUser', { persistUser() { saveUser({ userId: this.userId, + nickname: this.nickname, supplierIdentification: this.supplierIdentification, supplierId: this.supplierId, supplierName: this.supplierName, @@ -60,6 +63,7 @@ export const useUserStore = defineStore('joyfulSelectionUser', { const keyword = query.keyword || new URLSearchParams(window.location.search).get('keyword') || '' let nextUserId = query.userId || '' + let nextNickname if (keyword) { const sessionKeyword = String(keyword).replace(/ /g, '+') @@ -70,12 +74,15 @@ export const useUserStore = defineStore('joyfulSelectionUser', { }) const data = await postFunction('supplier-session', { keyword: sessionKeyword }) nextUserId = data?.userId || '' + nextNickname = data?.userInfo?.nickname || '' } if (nextUserId && nextUserId !== this.userId) { this.userId = nextUserId + this.nickname = '' this.pointsBalance = 0 } + if (nextNickname !== undefined) this.nickname = nextNickname if (!this.supplierIdentification) { this.supplierIdentification = DEFAULT_SUPPLIER_IDENTIFICATION } diff --git a/supplied-h5/src/view/joyful-selection/after-sale/detail/index.vue b/supplied-h5/src/view/joyful-selection/after-sale/detail/index.vue index e619fad..bb7cf0a 100644 --- a/supplied-h5/src/view/joyful-selection/after-sale/detail/index.vue +++ b/supplied-h5/src/view/joyful-selection/after-sale/detail/index.vue @@ -87,7 +87,7 @@ - +

填写物流单号

diff --git a/supplied-h5/src/view/joyful-selection/after-sale/exchange/index.vue b/supplied-h5/src/view/joyful-selection/after-sale/exchange/index.vue index 0c6a783..bfebcee 100644 --- a/supplied-h5/src/view/joyful-selection/after-sale/exchange/index.vue +++ b/supplied-h5/src/view/joyful-selection/after-sale/exchange/index.vue @@ -96,7 +96,7 @@
提交申请 - +

请选择换货原因

@@ -116,7 +116,7 @@
- +

选择换货商品

仅可选择价格为 ¥{{ originalProductPrice }} 的商品

diff --git a/supplied-h5/src/view/joyful-selection/after-sale/index/index.vue b/supplied-h5/src/view/joyful-selection/after-sale/index/index.vue index 4a5f132..2270278 100644 --- a/supplied-h5/src/view/joyful-selection/after-sale/index/index.vue +++ b/supplied-h5/src/view/joyful-selection/after-sale/index/index.vue @@ -3,7 +3,7 @@ - + diff --git a/supplied-h5/src/view/joyful-selection/after-sale/return/index.vue b/supplied-h5/src/view/joyful-selection/after-sale/return/index.vue index 2bdb049..6ce01a9 100644 --- a/supplied-h5/src/view/joyful-selection/after-sale/return/index.vue +++ b/supplied-h5/src/view/joyful-selection/after-sale/return/index.vue @@ -76,7 +76,7 @@
提交申请 - +

请选择退货原因

diff --git a/supplied-h5/src/view/joyful-selection/cart/components/JoyfulCartPanel.vue b/supplied-h5/src/view/joyful-selection/cart/components/JoyfulCartPanel.vue index d30a988..f8ff8e3 100644 --- a/supplied-h5/src/view/joyful-selection/cart/components/JoyfulCartPanel.vue +++ b/supplied-h5/src/view/joyful-selection/cart/components/JoyfulCartPanel.vue @@ -18,10 +18,10 @@ class="cart-item" >
@@ -52,10 +52,10 @@ @submit="handleCheckout" > 全选
diff --git a/supplied-h5/src/view/joyful-selection/cart/edit/index.vue b/supplied-h5/src/view/joyful-selection/cart/edit/index.vue index 6932316..26a166a 100644 --- a/supplied-h5/src/view/joyful-selection/cart/edit/index.vue +++ b/supplied-h5/src/view/joyful-selection/cart/edit/index.vue @@ -7,10 +7,10 @@
@@ -26,10 +26,10 @@ 全选 diff --git a/supplied-h5/src/view/joyful-selection/merchant/after-sale-detail.vue b/supplied-h5/src/view/joyful-selection/merchant/after-sale-detail.vue index 3b8c46b..48a1154 100644 --- a/supplied-h5/src/view/joyful-selection/merchant/after-sale-detail.vue +++ b/supplied-h5/src/view/joyful-selection/merchant/after-sale-detail.vue @@ -91,7 +91,7 @@ - +

填写换货发货信息

diff --git a/supplied-h5/src/view/joyful-selection/merchant/index.vue b/supplied-h5/src/view/joyful-selection/merchant/index.vue index 8ff9fdf..ecd9f41 100644 --- a/supplied-h5/src/view/joyful-selection/merchant/index.vue +++ b/supplied-h5/src/view/joyful-selection/merchant/index.vue @@ -3,7 +3,7 @@ - +
@@ -161,7 +161,7 @@ - +

填写发货信息

@@ -170,7 +170,7 @@
- +

填写换货发货信息

diff --git a/supplied-h5/src/view/joyful-selection/order/payment/index.vue b/supplied-h5/src/view/joyful-selection/order/payment/index.vue index 9f1ba58..459b55a 100644 --- a/supplied-h5/src/view/joyful-selection/order/payment/index.vue +++ b/supplied-h5/src/view/joyful-selection/order/payment/index.vue @@ -43,7 +43,7 @@ 立即支付 ¥{{ amountText }} - +
diff --git a/supplied-h5/src/view/joyful-selection/product-detail/index.vue b/supplied-h5/src/view/joyful-selection/product-detail/index.vue index 3f7191c..692009e 100644 --- a/supplied-h5/src/view/joyful-selection/product-detail/index.vue +++ b/supplied-h5/src/view/joyful-selection/product-detail/index.vue @@ -59,16 +59,16 @@
- - - - - - - + + + + + + + - +
购物车 @@ -251,7 +251,7 @@ export default { } .product-info { - margin-top: -4px; + margin-top: 12px; padding: 18px 16px 16px; } diff --git a/supplied-h5/src/view/joyful-selection/products/components/JoyfulSkuPopup.vue b/supplied-h5/src/view/joyful-selection/products/components/JoyfulSkuPopup.vue index 335f1d7..4809509 100644 --- a/supplied-h5/src/view/joyful-selection/products/components/JoyfulSkuPopup.vue +++ b/supplied-h5/src/view/joyful-selection/products/components/JoyfulSkuPopup.vue @@ -1,26 +1,70 @@