Commit a7dcdd6b4c4711fa79c93251f88a41bf2d4b908a

Authored by sanmu
0 parents

init

Too many changes to show.

To preserve performance only 48 of 49 files are displayed.

.eslintrc.cjs 0 → 100644
  1 +++ a/.eslintrc.cjs
  1 +/* eslint-env node */
  2 +require('@rushstack/eslint-patch/modern-module-resolution')
  3 +
  4 +module.exports = {
  5 + root: true,
  6 + 'extends': [
  7 + 'plugin:vue/vue3-essential',
  8 + 'eslint:recommended',
  9 + '@vue/eslint-config-typescript',
  10 + '@vue/eslint-config-prettier/skip-formatting',
  11 + ],
  12 + parserOptions: {
  13 + ecmaVersion: 'latest'
  14 + },
  15 + rules: {
  16 + 'vue/multi-word-component-names': 'off',
  17 + }
  18 +}
... ...
.gitignore 0 → 100644
  1 +++ a/.gitignore
  1 +# Logs
  2 +logs
  3 +*.log
  4 +npm-debug.log*
  5 +yarn-debug.log*
  6 +yarn-error.log*
  7 +pnpm-debug.log*
  8 +lerna-debug.log*
  9 +
  10 +node_modules
  11 +.DS_Store
  12 +dist
  13 +dist-ssr
  14 +coverage
  15 +*.local
  16 +
  17 +/cypress/videos/
  18 +/cypress/screenshots/
  19 +
  20 +# Editor directories and files
  21 +.vscode/*
  22 +!.vscode/extensions.json
  23 +.idea
  24 +*.suo
  25 +*.ntvs*
  26 +*.njsproj
  27 +*.sln
  28 +*.sw?
... ...
.prettierrc.json 0 → 100644
  1 +++ a/.prettierrc.json
  1 +{
  2 + "$schema": "https://json.schemastore.org/prettierrc",
  3 + "semi": false,
  4 + "tabWidth": 2,
  5 + "singleQuote": true,
  6 + "printWidth": 100,
  7 + "trailingComma": "none"
  8 +}
0 9 \ No newline at end of file
... ...
.vscode/extensions.json 0 → 100644
  1 +++ a/.vscode/extensions.json
  1 +{
  2 + "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
  3 +}
... ...
README.md 0 → 100644
  1 +++ a/README.md
  1 +# kelude-web
  2 +
  3 +This template should help get you started developing with Vue 3 in Vite.
  4 +
  5 +## Recommended IDE Setup
  6 +
  7 +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
  8 +
  9 +## Type Support for `.vue` Imports in TS
  10 +
  11 +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
  12 +
  13 +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
  14 +
  15 +1. Disable the built-in TypeScript Extension
  16 + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
  17 + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
  18 +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
  19 +
  20 +## Customize configuration
  21 +
  22 +See [Vite Configuration Reference](https://vitejs.dev/config/).
  23 +
  24 +## Project Setup
  25 +
  26 +```sh
  27 +npm install
  28 +```
  29 +
  30 +### Compile and Hot-Reload for Development
  31 +
  32 +```sh
  33 +npm run dev
  34 +```
  35 +
  36 +### Type-Check, Compile and Minify for Production
  37 +
  38 +```sh
  39 +npm run build
  40 +```
  41 +
  42 +### Run Unit Tests with [Vitest](https://vitest.dev/)
  43 +
  44 +```sh
  45 +npm run test:unit
  46 +```
  47 +
  48 +### Lint with [ESLint](https://eslint.org/)
  49 +
  50 +```sh
  51 +npm run lint
  52 +```
... ...
env.d.ts 0 → 100644
  1 +++ a/env.d.ts
  1 +/// <reference types="vite/client" />
... ...
index.html 0 → 100644
  1 +++ a/index.html
  1 +<!DOCTYPE html>
  2 +<html lang="en">
  3 + <head>
  4 + <meta charset="UTF-8">
  5 + <link rel="icon" href="/favicon.ico">
  6 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7 + <title>Vite App</title>
  8 + </head>
  9 + <body>
  10 + <div id="app"></div>
  11 + <script type="module" src="/src/main.ts"></script>
  12 + </body>
  13 +</html>
... ...
package.json 0 → 100644
  1 +++ a/package.json
  1 +{
  2 + "name": "kelude-web",
  3 + "version": "0.0.0",
  4 + "private": true,
  5 + "scripts": {
  6 + "dev": "vite",
  7 + "build": "run-p type-check build-only",
  8 + "preview": "vite preview",
  9 + "test:unit": "vitest",
  10 + "build-only": "vite build",
  11 + "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
  12 + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
  13 + "format": "prettier --write src/"
  14 + },
  15 + "dependencies": {
  16 + "autoprefixer": "^10.4.14",
  17 + "axios": "^1.4.0",
  18 + "pinia": "^2.0.36",
  19 + "postcss": "^8.4.23",
  20 + "sass": "^1.62.1",
  21 + "tailwindcss": "^3.3.2",
  22 + "vite-plugin-vuetify": "^1.0.2",
  23 + "vue": "^3.3.2",
  24 + "vue-router": "^4.2.0",
  25 + "vuetify": "^3.3.1"
  26 + },
  27 + "devDependencies": {
  28 + "@mdi/font": "^7.2.96",
  29 + "@rushstack/eslint-patch": "^1.2.0",
  30 + "@tsconfig/node18": "^2.0.1",
  31 + "@types/jsdom": "^21.1.1",
  32 + "@types/node": "^18.16.8",
  33 + "@vitejs/plugin-vue": "^4.2.3",
  34 + "@vitejs/plugin-vue-jsx": "^3.0.1",
  35 + "@vue/eslint-config-prettier": "^7.1.0",
  36 + "@vue/eslint-config-typescript": "^11.0.3",
  37 + "@vue/test-utils": "^2.3.2",
  38 + "@vue/tsconfig": "^0.4.0",
  39 + "eslint": "^8.39.0",
  40 + "eslint-plugin-vue": "^9.11.0",
  41 + "jsdom": "^22.0.0",
  42 + "material-design-icons-iconfont": "^6.7.0",
  43 + "npm-run-all": "^4.1.5",
  44 + "prettier": "^2.8.8",
  45 + "typescript": "~5.0.4",
  46 + "vite": "^4.3.5",
  47 + "vitest": "^0.31.0",
  48 + "vue-tsc": "^1.6.4"
  49 + }
  50 +}
... ...
postcss.config.js 0 → 100644
  1 +++ a/postcss.config.js
  1 +// eslint-disable-next-line no-undef
  2 +module.exports = {
  3 + plugins: {
  4 + tailwindcss: {},
  5 + autoprefixer: {},
  6 + }
  7 +}
0 8 \ No newline at end of file
... ...
public/favicon.ico 0 → 100644
No preview for this file type
src/App.vue 0 → 100644
  1 +++ a/src/App.vue
  1 +<script setup lang="ts">
  2 +import { onMounted, watchEffect, toValue } from 'vue'
  3 +import { RouterLink, RouterView } from 'vue-router'
  4 +import Header from '@/components/Header.vue'
  5 +import Footer from '@/components/Footer.vue'
  6 +import axios from 'axios'
  7 +import { useCategoryStore } from './stores/category'
  8 +import { useProductListStore } from './stores/product_list'
  9 +
  10 +const categoryStore = useCategoryStore()
  11 +const productListStore = useProductListStore()
  12 +
  13 +onMounted(() => {
  14 + // 请求分类列表
  15 + categoryStore.getList()
  16 +})
  17 +
  18 +watchEffect(() => {
  19 + if (toValue(categoryStore?.list)) {
  20 + const cId = categoryStore?.list?.[0]?.list?.[0]?.id
  21 + if (cId) productListStore.updateCategory(cId)
  22 + }
  23 +})
  24 +</script>
  25 +
  26 +<template>
  27 + <Header />
  28 + <div class="tw-min-h-[700px]">
  29 + <RouterView />
  30 + </div>
  31 + <Footer />
  32 +</template>
... ...
src/assets/1.jpeg 0 → 100644

24.5 KB

src/assets/banner1.png 0 → 100644

213 KB

src/assets/banner2.jpeg 0 → 100644

66 KB

src/assets/banner3.jpeg 0 → 100644

75.9 KB

src/assets/base.css 0 → 100644
  1 +++ a/src/assets/base.css
  1 +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
  2 +
  3 +/* Document
  4 + ========================================================================== */
  5 +
  6 +/**
  7 + * 1. Correct the line height in all browsers.
  8 + * 2. Prevent adjustments of font size after orientation changes in iOS.
  9 + */
  10 +
  11 +html {
  12 + line-height: 1.15; /* 1 */
  13 + -webkit-text-size-adjust: 100%; /* 2 */
  14 +}
  15 +
  16 +/* Sections
  17 + ========================================================================== */
  18 +
  19 +/**
  20 + * Remove the margin in all browsers.
  21 + */
  22 +
  23 +body {
  24 + margin: 0;
  25 +}
  26 +
  27 +/**
  28 + * Render the `main` element consistently in IE.
  29 + */
  30 +
  31 +main {
  32 + display: block;
  33 +}
  34 +
  35 +/**
  36 + * Correct the font size and margin on `h1` elements within `section` and
  37 + * `article` contexts in Chrome, Firefox, and Safari.
  38 + */
  39 +
  40 +h1 {
  41 + font-size: 2em;
  42 + margin: 0.67em 0;
  43 +}
  44 +
  45 +/* Grouping content
  46 + ========================================================================== */
  47 +
  48 +/**
  49 + * 1. Add the correct box sizing in Firefox.
  50 + * 2. Show the overflow in Edge and IE.
  51 + */
  52 +
  53 +hr {
  54 + box-sizing: content-box; /* 1 */
  55 + height: 0; /* 1 */
  56 + overflow: visible; /* 2 */
  57 +}
  58 +
  59 +/**
  60 + * 1. Correct the inheritance and scaling of font size in all browsers.
  61 + * 2. Correct the odd `em` font sizing in all browsers.
  62 + */
  63 +
  64 +pre {
  65 + font-family: monospace, monospace; /* 1 */
  66 + font-size: 1em; /* 2 */
  67 +}
  68 +
  69 +/* Text-level semantics
  70 + ========================================================================== */
  71 +
  72 +/**
  73 + * Remove the gray background on active links in IE 10.
  74 + */
  75 +
  76 +a {
  77 + background-color: transparent;
  78 +}
  79 +
  80 +/**
  81 + * 1. Remove the bottom border in Chrome 57-
  82 + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
  83 + */
  84 +
  85 +abbr[title] {
  86 + border-bottom: none; /* 1 */
  87 + text-decoration: underline; /* 2 */
  88 + text-decoration: underline dotted; /* 2 */
  89 +}
  90 +
  91 +/**
  92 + * Add the correct font weight in Chrome, Edge, and Safari.
  93 + */
  94 +
  95 +b,
  96 +strong {
  97 + font-weight: bolder;
  98 +}
  99 +
  100 +/**
  101 + * 1. Correct the inheritance and scaling of font size in all browsers.
  102 + * 2. Correct the odd `em` font sizing in all browsers.
  103 + */
  104 +
  105 +code,
  106 +kbd,
  107 +samp {
  108 + font-family: monospace, monospace; /* 1 */
  109 + font-size: 1em; /* 2 */
  110 +}
  111 +
  112 +/**
  113 + * Add the correct font size in all browsers.
  114 + */
  115 +
  116 +small {
  117 + font-size: 80%;
  118 +}
  119 +
  120 +/**
  121 + * Prevent `sub` and `sup` elements from affecting the line height in
  122 + * all browsers.
  123 + */
  124 +
  125 +sub,
  126 +sup {
  127 + font-size: 75%;
  128 + line-height: 0;
  129 + position: relative;
  130 + vertical-align: baseline;
  131 +}
  132 +
  133 +sub {
  134 + bottom: -0.25em;
  135 +}
  136 +
  137 +sup {
  138 + top: -0.5em;
  139 +}
  140 +
  141 +/* Embedded content
  142 + ========================================================================== */
  143 +
  144 +/**
  145 + * Remove the border on images inside links in IE 10.
  146 + */
  147 +
  148 +img {
  149 + border-style: none;
  150 +}
  151 +
  152 +/* Forms
  153 + ========================================================================== */
  154 +
  155 +/**
  156 + * 1. Change the font styles in all browsers.
  157 + * 2. Remove the margin in Firefox and Safari.
  158 + */
  159 +
  160 +button,
  161 +input,
  162 +optgroup,
  163 +select,
  164 +textarea {
  165 + font-family: inherit; /* 1 */
  166 + font-size: 100%; /* 1 */
  167 + line-height: 1.15; /* 1 */
  168 + margin: 0; /* 2 */
  169 +}
  170 +
  171 +/**
  172 + * Show the overflow in IE.
  173 + * 1. Show the overflow in Edge.
  174 + */
  175 +
  176 +button,
  177 +input {
  178 + /* 1 */
  179 + overflow: visible;
  180 +}
  181 +
  182 +/**
  183 + * Remove the inheritance of text transform in Edge, Firefox, and IE.
  184 + * 1. Remove the inheritance of text transform in Firefox.
  185 + */
  186 +
  187 +button,
  188 +select {
  189 + /* 1 */
  190 + text-transform: none;
  191 +}
  192 +
  193 +/**
  194 + * Correct the inability to style clickable types in iOS and Safari.
  195 + */
  196 +
  197 +button,
  198 +[type='button'],
  199 +[type='reset'],
  200 +[type='submit'] {
  201 + -webkit-appearance: button;
  202 +}
  203 +
  204 +/**
  205 + * Remove the inner border and padding in Firefox.
  206 + */
  207 +
  208 +button::-moz-focus-inner,
  209 +[type='button']::-moz-focus-inner,
  210 +[type='reset']::-moz-focus-inner,
  211 +[type='submit']::-moz-focus-inner {
  212 + border-style: none;
  213 + padding: 0;
  214 +}
  215 +
  216 +/**
  217 + * Restore the focus styles unset by the previous rule.
  218 + */
  219 +
  220 +button:-moz-focusring,
  221 +[type='button']:-moz-focusring,
  222 +[type='reset']:-moz-focusring,
  223 +[type='submit']:-moz-focusring {
  224 + outline: 1px dotted ButtonText;
  225 +}
  226 +
  227 +/**
  228 + * Correct the padding in Firefox.
  229 + */
  230 +
  231 +fieldset {
  232 + padding: 0.35em 0.75em 0.625em;
  233 +}
  234 +
  235 +/**
  236 + * 1. Correct the text wrapping in Edge and IE.
  237 + * 2. Correct the color inheritance from `fieldset` elements in IE.
  238 + * 3. Remove the padding so developers are not caught out when they zero out
  239 + * `fieldset` elements in all browsers.
  240 + */
  241 +
  242 +legend {
  243 + box-sizing: border-box; /* 1 */
  244 + color: inherit; /* 2 */
  245 + display: table; /* 1 */
  246 + max-width: 100%; /* 1 */
  247 + padding: 0; /* 3 */
  248 + white-space: normal; /* 1 */
  249 +}
  250 +
  251 +/**
  252 + * Add the correct vertical alignment in Chrome, Firefox, and Opera.
  253 + */
  254 +
  255 +progress {
  256 + vertical-align: baseline;
  257 +}
  258 +
  259 +/**
  260 + * Remove the default vertical scrollbar in IE 10+.
  261 + */
  262 +
  263 +textarea {
  264 + overflow: auto;
  265 +}
  266 +
  267 +/**
  268 + * 1. Add the correct box sizing in IE 10.
  269 + * 2. Remove the padding in IE 10.
  270 + */
  271 +
  272 +[type='checkbox'],
  273 +[type='radio'] {
  274 + box-sizing: border-box; /* 1 */
  275 + padding: 0; /* 2 */
  276 +}
  277 +
  278 +/**
  279 + * Correct the cursor style of increment and decrement buttons in Chrome.
  280 + */
  281 +
  282 +[type='number']::-webkit-inner-spin-button,
  283 +[type='number']::-webkit-outer-spin-button {
  284 + height: auto;
  285 +}
  286 +
  287 +/**
  288 + * 1. Correct the odd appearance in Chrome and Safari.
  289 + * 2. Correct the outline style in Safari.
  290 + */
  291 +
  292 +[type='search'] {
  293 + -webkit-appearance: textfield; /* 1 */
  294 + outline-offset: -2px; /* 2 */
  295 +}
  296 +
  297 +/**
  298 + * Remove the inner padding in Chrome and Safari on macOS.
  299 + */
  300 +
  301 +[type='search']::-webkit-search-decoration {
  302 + -webkit-appearance: none;
  303 +}
  304 +
  305 +/**
  306 + * 1. Correct the inability to style clickable types in iOS and Safari.
  307 + * 2. Change font properties to `inherit` in Safari.
  308 + */
  309 +
  310 +::-webkit-file-upload-button {
  311 + -webkit-appearance: button; /* 1 */
  312 + font: inherit; /* 2 */
  313 +}
  314 +
  315 +/* Interactive
  316 + ========================================================================== */
  317 +
  318 +/*
  319 + * Add the correct display in Edge, IE 10+, and Firefox.
  320 + */
  321 +
  322 +details {
  323 + display: block;
  324 +}
  325 +
  326 +/*
  327 + * Add the correct display in all browsers.
  328 + */
  329 +
  330 +summary {
  331 + display: list-item;
  332 +}
  333 +
  334 +/* Misc
  335 + ========================================================================== */
  336 +
  337 +/**
  338 + * Add the correct display in IE 10+.
  339 + */
  340 +
  341 +template {
  342 + display: none;
  343 +}
  344 +
  345 +/**
  346 + * Add the correct display in IE 10.
  347 + */
  348 +
  349 +[hidden] {
  350 + display: none;
  351 +}
  352 +
  353 +li {
  354 + list-style: none;
  355 +}
  356 +
  357 +a {
  358 + color: #fff;
  359 + text-decoration: none;
  360 +}
... ...
src/assets/logo.png 0 → 100644

2.28 KB

src/assets/logo.svg 0 → 100644
  1 +++ a/src/assets/logo.svg
  1 +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
... ...
src/assets/main.css 0 → 100644
  1 +++ a/src/assets/main.css
  1 +@import './base.css';
  2 +
  3 +@tailwind base;
  4 +@tailwind components;
  5 +@tailwind utilities;
... ...
src/components/CategoryList.vue 0 → 100644
  1 +++ a/src/components/CategoryList.vue
  1 +<template>
  2 + <v-container>
  3 + <div height="100" class="pa-2">
  4 + <v-row>
  5 + <div class="tw-pr-0 tw-font-bold tw-w-[95px] tw-h-[36px] tw-leading-[36px]">一级类别:</div>
  6 + <v-col class="pa-0">
  7 + <v-btn
  8 + v-for="(item, index) in categoryStore.list"
  9 + :key="index"
  10 + variant="text"
  11 + @click="handleCategoryClick(item)"
  12 + :color="
  13 + categoryStore.selectedCategory === item.categoryDisplayName ? 'blue-accent-2' : ''
  14 + "
  15 + >
  16 + {{ item.categoryDisplayName }}
  17 + </v-btn>
  18 + </v-col>
  19 + </v-row>
  20 + <v-row>
  21 + <div class="tw-pr-0 tw-font-bold tw-w-[95px] tw-h-[36px] tw-leading-[36px]">二级类别:</div>
  22 + <v-col class="pa-0">
  23 + <v-btn
  24 + v-for="(item, index) in subCategoryList"
  25 + :key="index"
  26 + variant="text"
  27 + @click="handleSubCategoryClick(item.id)"
  28 + :color="categoryStore.selectedSubCategory === item.id ? 'blue-accent-2' : ''"
  29 + >
  30 + {{ item.name }}
  31 + </v-btn>
  32 + </v-col>
  33 + </v-row>
  34 + </div>
  35 + </v-container>
  36 +</template>
  37 +
  38 +<script setup lang="ts">
  39 +import { useCategoryStore } from '@/stores/category'
  40 +import type { CategoryRootType } from '@/type'
  41 +import { computed } from 'vue'
  42 +
  43 +const categoryStore = useCategoryStore()
  44 +
  45 +const handleCategoryClick = (item: CategoryRootType) => {
  46 + categoryStore.updateCategory(item.categoryDisplayName)
  47 + categoryStore.updateSubCategory(item.list[0].id)
  48 +}
  49 +
  50 +const handleSubCategoryClick = (value: string) => {
  51 + categoryStore.updateSubCategory(value)
  52 +}
  53 +
  54 +const subCategoryList = computed(() => {
  55 + if (categoryStore.selectedCategory) {
  56 + const tmp = categoryStore.list.filter(
  57 + (item) => item.categoryDisplayName === categoryStore.selectedCategory
  58 + )
  59 + return tmp?.[0]?.list || []
  60 + }
  61 + return []
  62 +})
  63 +</script>
... ...
src/components/Footer.vue 0 → 100644
  1 +++ a/src/components/Footer.vue
  1 +<template>
  2 + <div class="tw-bottom-0 tw-leading-10 tw-h-10 tw-text-center tw-w-full tw-pt-[100px]">
  3 + 备案:xxxxs
  4 + </div>
  5 +</template>
  6 +
  7 +<script setup lang="ts"></script>
  8 +
  9 +<style lang="less" scoped></style>
... ...
src/components/Header.vue 0 → 100644
  1 +++ a/src/components/Header.vue
  1 +<template>
  2 + <v-container>
  3 + <div class="tw-m-auto">
  4 + <div class="tw-mr-[32px] tw-float-left tw-h-[64px] tw-mt-[-4px]">
  5 + <img src="@/assets/logo.png" />
  6 + </div>
  7 + <div class="tw-m-auto">
  8 + <v-text-field
  9 + density="comfortable"
  10 + label="请输入搜索内容"
  11 + hide-details="auto"
  12 + variant="solo"
  13 + append-inner-icon="mdi-magnify"
  14 + ></v-text-field>
  15 + </div>
  16 + </div>
  17 + </v-container>
  18 + <div class="tabs tw-mb-[24px]">
  19 + <div class="tw-max-w-[1200px] tw-mx-auto">
  20 + <v-tabs v-model="tab" bg-color="blue-darken-2" slider-color="yellow-darken-4">
  21 + <v-tab :value="1" to="/">首页 </v-tab>
  22 + <v-tab :value="2" to="/products">产品中心</v-tab>
  23 + <v-tab :value="3" to="/contact">联系我们</v-tab>
  24 + </v-tabs>
  25 + </div>
  26 + </div>
  27 +</template>
  28 +
  29 +<script setup lang="ts">
  30 +import { ref, onMounted } from 'vue'
  31 +
  32 +const tab = ref(1)
  33 +const handleTabsChange = (val) => {
  34 + console.log(12121)
  35 +}
  36 +</script>
  37 +
  38 +<style lang="scss" scoped>
  39 +.tabs {
  40 + background-color: #1976d2;
  41 +}
  42 +</style>
... ...
src/components/HomeCategoryList.vue 0 → 100644
  1 +++ a/src/components/HomeCategoryList.vue
  1 +<template>
  2 + <v-container class="">
  3 + <div class="text-blue-darken-2 text-h3 tw-text-center tw-mb-16">{{ title }}</div>
  4 + <v-item-group multiple>
  5 + <v-row>
  6 + <v-col v-for="(item, index) in list" :key="index" cols="12" lg="3" md="4" sm="6">
  7 + <v-hover v-slot="{ isHovering, props }" open-delay="200">
  8 + <v-card
  9 + :elevation="isHovering ? 16 : 2"
  10 + :class="{ 'on-hover': isHovering }"
  11 + class="mx-auto"
  12 + height="350"
  13 + width="260"
  14 + v-bind="props"
  15 + >
  16 + <v-img :src="item.imageUrl" />
  17 + <v-card-text class="text-center font-weight-medium text-subtitle-1">
  18 + {{ item.name }}
  19 + </v-card-text>
  20 + </v-card>
  21 + </v-hover>
  22 + </v-col>
  23 + </v-row>
  24 + </v-item-group>
  25 + </v-container>
  26 + <!-- <li class="tw-flex-1 tw-flex-row item tw-mb-8"></li> -->
  27 +</template>
  28 +
  29 +<script setup lang="ts">
  30 +import type { Category } from '@/type'
  31 +import { onMounted, ref } from 'vue'
  32 +
  33 +defineProps<{
  34 + title: string
  35 + list: Category[]
  36 +}>()
  37 +</script>
... ...
src/components/__tests__/HelloWorld.spec.ts 0 → 100644
  1 +++ a/src/components/__tests__/HelloWorld.spec.ts
  1 +import { describe, it, expect } from 'vitest'
  2 +
  3 +import { mount } from '@vue/test-utils'
  4 +import HelloWorld from '../HelloWorld.vue'
  5 +
  6 +describe('HelloWorld', () => {
  7 + it('renders properly', () => {
  8 + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
  9 + expect(wrapper.text()).toContain('Hello Vitest')
  10 + })
  11 +})
... ...
src/components/icons/IconCommunity.vue 0 → 100644
  1 +++ a/src/components/icons/IconCommunity.vue
  1 +<template>
  2 + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
  3 + <path
  4 + d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
  5 + />
  6 + </svg>
  7 +</template>
... ...
src/components/icons/IconDocumentation.vue 0 → 100644
  1 +++ a/src/components/icons/IconDocumentation.vue
  1 +<template>
  2 + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
  3 + <path
  4 + d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
  5 + />
  6 + </svg>
  7 +</template>
... ...
src/components/icons/IconEcosystem.vue 0 → 100644
  1 +++ a/src/components/icons/IconEcosystem.vue
  1 +<template>
  2 + <svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
  3 + <path
  4 + d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
  5 + />
  6 + </svg>
  7 +</template>
... ...
src/components/icons/IconSupport.vue 0 → 100644
  1 +++ a/src/components/icons/IconSupport.vue
  1 +<template>
  2 + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
  3 + <path
  4 + d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
  5 + />
  6 + </svg>
  7 +</template>
... ...
src/components/icons/IconTooling.vue 0 → 100644
  1 +++ a/src/components/icons/IconTooling.vue
  1 +<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
  2 +<template>
  3 + <svg
  4 + xmlns="http://www.w3.org/2000/svg"
  5 + xmlns:xlink="http://www.w3.org/1999/xlink"
  6 + aria-hidden="true"
  7 + role="img"
  8 + class="iconify iconify--mdi"
  9 + width="24"
  10 + height="24"
  11 + preserveAspectRatio="xMidYMid meet"
  12 + viewBox="0 0 24 24"
  13 + >
  14 + <path
  15 + d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
  16 + fill="currentColor"
  17 + ></path>
  18 + </svg>
  19 +</template>
... ...
src/constant.ts 0 → 100644
  1 +++ a/src/constant.ts
... ...
src/constant/index.ts 0 → 100644
  1 +++ a/src/constant/index.ts
  1 +export const categoryMap = {}
... ...
src/main.ts 0 → 100644
  1 +++ a/src/main.ts
  1 +import './assets/main.css'
  2 +
  3 +// Vuetify
  4 +import 'vuetify/styles'
  5 +import { createVuetify } from 'vuetify'
  6 +// import 'material-design-icons-iconfont/dist/material-design-icons.css'
  7 +import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
  8 +
  9 +import { createApp } from 'vue'
  10 +import { createPinia } from 'pinia'
  11 +
  12 +import App from './App.vue'
  13 +import router from './router'
  14 +
  15 +const app = createApp(App)
  16 +
  17 +const vuetify = createVuetify()
  18 +
  19 +app.use(createPinia())
  20 +app.use(router)
  21 +
  22 +app.use(vuetify)
  23 +
  24 +app.mount('#app')
... ...
src/router/index.ts 0 → 100644
  1 +++ a/src/router/index.ts
  1 +import { createRouter, createWebHistory } from 'vue-router'
  2 +import Home from '../views/Home.vue'
  3 +import Contact from '../views/Contact.vue'
  4 +import ProductList from '../views/ProductList.vue'
  5 +import ProductDetail from '../views/ProductDetail.vue'
  6 +
  7 +const router = createRouter({
  8 + history: createWebHistory(import.meta.env.BASE_URL),
  9 + routes: [
  10 + {
  11 + path: '/',
  12 + name: 'home',
  13 + component: Home
  14 + },
  15 + {
  16 + path: '/products/detail/:id',
  17 + name: 'detail',
  18 + component: ProductDetail
  19 + },
  20 + {
  21 + path: '/products',
  22 + name: 'products',
  23 + component: ProductList
  24 + },
  25 + {
  26 + path: '/contact',
  27 + name: 'contact',
  28 + component: Contact
  29 + }
  30 + // {
  31 + // path: '/about',
  32 + // name: 'about',
  33 + // // route level code-splitting
  34 + // // this generates a separate chunk (About.[hash].js) for this route
  35 + // // which is lazy-loaded when the route is visited.
  36 + // // component: () => import('../views/AboutView.vue')
  37 + // }
  38 + ]
  39 +})
  40 +
  41 +export default router
... ...
src/service.ts 0 → 100644
  1 +++ a/src/service.ts
  1 +import axios from 'axios'
  2 +import type { ProductListQuery } from './type'
  3 +
  4 +export const getCategoryList = () => {
  5 + return axios.post('/shop/product/category', {})
  6 +}
  7 +
  8 +export const getProductList = (params: ProductListQuery) => {
  9 + return axios.post('/shop/product/list', params)
  10 +}
  11 +
  12 +export const getDetail = (params: { id: string }) => {
  13 + return axios.post('/shop/product/detail', params)
  14 +}
... ...
src/stores/category.ts 0 → 100644
  1 +++ a/src/stores/category.ts
  1 +import { getCategoryList } from './../service'
  2 +import { ref } from 'vue'
  3 +import { defineStore } from 'pinia'
  4 +import type { Category, CategoryRootType } from '@/type'
  5 +
  6 +export const useCategoryStore = defineStore('category', () => {
  7 + const list = ref<CategoryRootType[]>([])
  8 + const selectedCategory = ref('') // 选中的一级类别
  9 + const selectedSubCategory = ref('') // 选中的二级类别
  10 +
  11 + const getList = () => {
  12 + getCategoryList().then((res) => {
  13 + const rootList = res.data?.data?.rootCategoryList
  14 + list.value = rootList || []
  15 + selectedCategory.value = rootList[0].categoryDisplayName
  16 + selectedSubCategory.value = rootList[0].list[0].id
  17 + })
  18 + }
  19 +
  20 + const updateCategory = (value: string) => {
  21 + selectedCategory.value = value
  22 + }
  23 +
  24 + const updateSubCategory = (value: string) => {
  25 + selectedSubCategory.value = value
  26 + }
  27 +
  28 + return { list, selectedCategory, selectedSubCategory, getList, updateCategory, updateSubCategory }
  29 +})
... ...
src/stores/product_list.ts 0 → 100644
  1 +++ a/src/stores/product_list.ts
  1 +import { getProductList } from './../service'
  2 +import { ref } from 'vue'
  3 +import { defineStore } from 'pinia'
  4 +import type { Product, ProductListQuery } from '@/type'
  5 +
  6 +export const useProductListStore = defineStore('productList', () => {
  7 + const list = ref<Product[]>([])
  8 + const productCategoryId = ref('') // 选中的类别
  9 + const keywork = ref(null)
  10 + const pageNo = ref('')
  11 + const pageSize = ref(20)
  12 + const total = ref(0)
  13 +
  14 + const getList = (params: ProductListQuery) => {
  15 + if (params.productCategoryId) {
  16 + getProductList(params).then((res) => {
  17 + const data = res.data?.data || {}
  18 + list.value = data?.records || []
  19 + total.value = data?.total || 0
  20 + })
  21 + }
  22 + }
  23 +
  24 + const updateCategory = (value: string) => {
  25 + productCategoryId.value = value
  26 + }
  27 +
  28 + return { total, list, getList, updateCategory }
  29 +})
... ...
src/type.d.ts 0 → 100644
  1 +++ a/src/type.d.ts
  1 +import { Category } from './type.d'
  2 +export interface Category {
  3 + name: string
  4 + imageUrl: string
  5 + id: string
  6 +}
  7 +
  8 +export interface CategoryRootType {
  9 + categoryDisplayName: string
  10 + list: Category[]
  11 +}
  12 +
  13 +export interface Product {
  14 + name: string
  15 + id: string
  16 + imageUrl: string
  17 +}
  18 +
  19 +export interface ProductListQuery {
  20 + productCategoryId: string
  21 + keyword?: string
  22 + pageNo: number
  23 + pageSize: number
  24 +}
... ...
src/views/Contact.vue 0 → 100644
  1 +++ a/src/views/Contact.vue
  1 +<template>
  2 + <v-card width="800" class="pa-10 tw-m-auto">
  3 + <div class="tw-text-center tw-text-4xl tw-mb-20">联系我们</div>
  4 + <h3 class="text-h5 tw-mb-5">联系我们</h3>
  5 + <div class="tw-mb-10">
  6 + <label class="text-subtitle-1 tw-mr-4 tw-w-20 tw-inline-block">官网地址</label>
  7 + <span>http://www.canrd.com</span>
  8 + </div>
  9 +
  10 + <h3 class="text-h5 tw-mb-5">技术中心</h3>
  11 + <div>
  12 + <label class="text-subtitle-1 tw-mr-4 tw-w-20 tw-inline-block">QQ</label>
  13 + <span>3003597584/2902385824</span>
  14 + </div>
  15 + <div class="tw-mb-10">
  16 + <label class="text-subtitle-1 tw-mr-4 tw-w-20 tw-inline-block">Email</label>
  17 + <span>Linda@canrd.com</span>
  18 + </div>
  19 + <div>
  20 + <h3 class="text-h5 tw-mb-5">关注微信</h3>
  21 + <div></div>
  22 + </div>
  23 + </v-card>
  24 +</template>
  25 +
  26 +<script setup lang="ts"></script>
  27 +
  28 +<style lang="less" scoped></style>
... ...
src/views/Home.vue 0 → 100644
  1 +++ a/src/views/Home.vue
  1 +<template>
  2 + <v-container class="mx-auto content">
  3 + <v-carousel cycle height="360" hide-delimiter-background show-arrows="hover" class="tw-mb-16">
  4 + <v-carousel-item v-for="(slide, i) in slides" :key="i" :src="slide" cover> </v-carousel-item>
  5 + </v-carousel>
  6 + <div v-for="item in store.list" :key="item.categoryDisplayName" class="tw-mb-[64px]">
  7 + <HomeProductList :title="item.categoryDisplayName" :list="item.list" />
  8 + </div>
  9 + </v-container>
  10 +</template>
  11 +
  12 +<script setup lang="ts">
  13 +import HomeProductList from '@/components/HomeCategoryList.vue'
  14 +import { useCategoryStore } from '@/stores/category'
  15 +const slides = ['src/assets/banner1.png', 'src/assets/banner2.jpeg', 'src/assets/banner3.jpeg']
  16 +
  17 +const store = useCategoryStore()
  18 +</script>
  19 +
  20 +<style lang="scss" scoped>
  21 +.content {
  22 + max-width: 1200px;
  23 +}
  24 +</style>
... ...
src/views/ProductDetail.vue 0 → 100644
  1 +++ a/src/views/ProductDetail.vue
  1 +<template>
  2 + <v-container class="pa-1">
  3 + <v-breadcrumbs class="pt-0" :items="['首页', '产品中心', '详情']"></v-breadcrumbs>
  4 + <v-card max-width="1000" class="tw-m-auto tw-mb-[32px]">
  5 + <v-row class="ma-0">
  6 + <div class="tw-float-left tw-w-[300px]">
  7 + <v-carousel
  8 + show-arrows="hover"
  9 + hide-delimiter-background
  10 + delimiter-icon="mdi-square"
  11 + class="tw-float-left"
  12 + height="300"
  13 + v-model="slide"
  14 + >
  15 + <v-carousel-item
  16 + cover
  17 + v-for="(slide, i) in info.productimageliststore"
  18 + :src="slide.url"
  19 + :key="i"
  20 + >
  21 + </v-carousel-item>
  22 + </v-carousel>
  23 + </div>
  24 + <v-col>
  25 + <v-card-title class="text-h5"> {{ info.name }} </v-card-title>
  26 + <v-row>
  27 + <v-col>
  28 + <v-card-text class="tw-leading-[10px]">品牌:{{ info.brandName }}</v-card-text>
  29 + </v-col>
  30 + <v-col>
  31 + <v-card-text>产品分类:{{ info.brandName }}</v-card-text>
  32 + </v-col>
  33 + </v-row>
  34 + <v-row>
  35 + <v-col>
  36 + <v-card-text>产品型号:{{ info.model }}</v-card-text>
  37 + </v-col>
  38 + <v-col>
  39 + <v-card-text>{{ info.basename1 }}:{{ info.basecore1 }}</v-card-text>
  40 + </v-col>
  41 + </v-row>
  42 + <v-row>
  43 + <v-col>
  44 + <v-card-text>{{ info.basename2 }}:{{ info.basecore2 }}</v-card-text>
  45 + </v-col>
  46 + <v-col>
  47 + <v-card-text>{{ info.basename2 }}:{{ info.basecore3 }}</v-card-text>
  48 + </v-col>
  49 + </v-row>
  50 + </v-col>
  51 + </v-row>
  52 + </v-card>
  53 + <div class="tw-m-auto tw-max-w-[1000px]">
  54 + <v-tabs v-model="tab" color="blue-lighten-1" align-tabs="start">
  55 + <v-tab :value="1">商品介绍</v-tab>
  56 + <v-tab :value="2">规格参数</v-tab>
  57 + <!-- <v-tab :value="3">商品百科</v-tab> -->
  58 + </v-tabs>
  59 + <v-window v-model="tab" class="tw-p-[24px]">
  60 + <v-window-item key="1" :value="1">
  61 + <div v-html="info.physicalproperty"></div>
  62 + <div v-html="info.storage"></div>
  63 + </v-window-item>
  64 + <v-window-item key="2" :value="2"> 参数规格</v-window-item>
  65 + <!-- <v-window-item key="3" :value="3"> 2 </v-window-item> -->
  66 + </v-window>
  67 + </div>
  68 + </v-container>
  69 +</template>
  70 +
  71 +<script setup lang="ts">
  72 +import { getDetail } from '@/service'
  73 +import { onMounted, ref } from 'vue'
  74 +import { useRoute } from 'vue-router'
  75 +
  76 +const route = useRoute()
  77 +const info = ref({
  78 + productimageliststore: []
  79 +})
  80 +
  81 +onMounted(() => {
  82 + getDetail({ id: route.params.id as string }).then((res) => {
  83 + const data = res.data.data || {}
  84 + console.log('%c [ data ]-117', 'font-size:13px; background:pink; color:#bf2c9f;', data)
  85 + data.productimageliststore = JSON.parse(data.productimageliststore) || []
  86 + data.productimageliststore = data.productimageliststore.map((item) => ({
  87 + ...item,
  88 + url: `http://112.74.45.244:8100/api/show/image?fileKey=${item.fileKey}`
  89 + }))
  90 + info.value = data
  91 + })
  92 +})
  93 +
  94 +const tab = ref(0)
  95 +const slide = ref(0)
  96 +</script>
  97 +
  98 +<style lang="less" scoped></style>
... ...
src/views/ProductList.vue 0 → 100644
  1 +++ a/src/views/ProductList.vue
  1 +<template>
  2 + <div class="tw-m-auto">
  3 + <CategoryList />
  4 + <v-container class="">
  5 + <v-item-group multiple>
  6 + <v-row>
  7 + <v-col v-for="(item, i) in productStore.list" :key="i" cols="12" lg="3" md="4" sm="6">
  8 + <v-hover v-slot="{ isHovering, props }" open-delay="200">
  9 + <v-card
  10 + :elevation="isHovering ? 16 : 2"
  11 + :class="{ 'on-hover': isHovering }"
  12 + class="mx-auto"
  13 + height="350"
  14 + width="260"
  15 + v-bind="props"
  16 + :to="`/products/detail/${item.id}`"
  17 + >
  18 + <v-img :src="item.imageUrl">
  19 + <!-- <v-expand-transition>
  20 + <div
  21 + v-if="isHovering"
  22 + class="d-flex transition-fast-in-fast-out bg-orange-darken-2 v-card--reveal tw-p-[12px] tw-text-justify"
  23 + style="height: 100%"
  24 + >
  25 + 产品描述描述描述描述描述描述描述描述
  26 + </div>
  27 + </v-expand-transition> -->
  28 + </v-img>
  29 + <v-card-text class="tw-text-left">{{ item.name }}</v-card-text>
  30 + </v-card>
  31 + </v-hover>
  32 + </v-col>
  33 + </v-row>
  34 + </v-item-group>
  35 + </v-container>
  36 + </div>
  37 +</template>
  38 +
  39 +<script setup lang="ts">
  40 +import { useProductListStore } from '@/stores/product_list'
  41 +import { useCategoryStore } from '@/stores/category'
  42 +import CategoryList from '@/components/CategoryList.vue'
  43 +import { watchEffect } from 'vue'
  44 +
  45 +const productStore = useProductListStore()
  46 +const categoryStore = useCategoryStore()
  47 +watchEffect(() => {
  48 + if (categoryStore.selectedSubCategory) {
  49 + productStore.getList({
  50 + // productCategoryId: '78b86c6e917841cf9a292234f2805e24',
  51 + productCategoryId: categoryStore.selectedSubCategory,
  52 + pageNo: 1,
  53 + pageSize: 20
  54 + })
  55 + }
  56 +})
  57 +</script>
  58 +
  59 +<style lang="scss" scoped></style>
... ...
tailwind.config.js 0 → 100644
  1 +++ a/tailwind.config.js
  1 +/** @type {import('tailwindcss').Config} */
  2 +export default {
  3 + corePlugins: {
  4 + preflight: false,
  5 + },
  6 + prefix: 'tw-',
  7 + content: [
  8 + "./index.html",
  9 + "./src/**/*.{vue,js,ts,jsx,tsx}",
  10 + ],
  11 + theme: {
  12 + extend: {
  13 + w: {
  14 + screen: {
  15 + 1200: '1200px'
  16 + }
  17 + }
  18 + },
  19 + },
  20 + plugins: [],
  21 +}
0 22 \ No newline at end of file
... ...
tsconfig.app.json 0 → 100644
  1 +++ a/tsconfig.app.json
  1 +{
  2 + "extends": "@vue/tsconfig/tsconfig.dom.json",
  3 + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  4 + "exclude": ["src/**/__tests__/*"],
  5 + "compilerOptions": {
  6 + "composite": true,
  7 + "baseUrl": ".",
  8 + "paths": {
  9 + "@/*": ["./src/*"]
  10 + }
  11 + }
  12 +}
... ...
tsconfig.json 0 → 100644
  1 +++ a/tsconfig.json
  1 +{
  2 + "files": [],
  3 + "references": [
  4 + {
  5 + "path": "./tsconfig.node.json"
  6 + },
  7 + {
  8 + "path": "./tsconfig.app.json"
  9 + },
  10 + {
  11 + "path": "./tsconfig.vitest.json"
  12 + }
  13 + ]
  14 +}
... ...
tsconfig.node.json 0 → 100644
  1 +++ a/tsconfig.node.json
  1 +{
  2 + "extends": "@tsconfig/node18/tsconfig.json",
  3 + "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
  4 + "compilerOptions": {
  5 + "composite": true,
  6 + "module": "ESNext",
  7 + "types": ["node"]
  8 + }
  9 +}
... ...
tsconfig.vitest.json 0 → 100644
  1 +++ a/tsconfig.vitest.json
  1 +{
  2 + "extends": "./tsconfig.app.json",
  3 + "exclude": [],
  4 + "compilerOptions": {
  5 + "composite": true,
  6 + "lib": [],
  7 + "types": ["node", "jsdom"]
  8 + }
  9 +}
... ...
vite.config.ts 0 → 100644
  1 +++ a/vite.config.ts
  1 +import { fileURLToPath, URL } from 'node:url'
  2 +
  3 +import { defineConfig } from 'vite'
  4 +import vue from '@vitejs/plugin-vue'
  5 +import vueJsx from '@vitejs/plugin-vue-jsx'
  6 +
  7 +import vuetify from 'vite-plugin-vuetify'
  8 +
  9 +// https://vitejs.dev/config/
  10 +export default defineConfig({
  11 + plugins: [vue(), vueJsx(), vuetify()],
  12 + resolve: {
  13 + alias: {
  14 + '@': fileURLToPath(new URL('./src', import.meta.url))
  15 + }
  16 + },
  17 + server: {
  18 + proxy: {
  19 + '/shop': {
  20 + target: 'http://39.108.227.113:8002'
  21 + }
  22 + }
  23 + }
  24 +})
... ...
vitest.config.ts 0 → 100644
  1 +++ a/vitest.config.ts
  1 +import { fileURLToPath } from 'node:url'
  2 +import { mergeConfig } from 'vite'
  3 +import { configDefaults, defineConfig } from 'vitest/config'
  4 +import viteConfig from './vite.config'
  5 +
  6 +export default mergeConfig(
  7 + viteConfig,
  8 + defineConfig({
  9 + test: {
  10 + environment: 'jsdom',
  11 + exclude: [...configDefaults.exclude, 'e2e/*'],
  12 + root: fileURLToPath(new URL('./', import.meta.url)),
  13 + transformMode: {
  14 + web: [/\.[jt]sx$/],
  15 + },
  16 + }
  17 + })
  18 +)
... ...