后台编写王朝
This commit is contained in:
parent
4f1b8cbe9d
commit
2bbb32adf6
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -22,7 +22,7 @@
|
||||
"editor.defaultFormatter": "foxundermoon.shell-format"
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "Vue.volar"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
|
4
env/.env
vendored
4
env/.env
vendored
@ -7,9 +7,11 @@ VITE_WX_APPID = 'wxa2abb91f64032a2b'
|
||||
# h5部署网站的base,配置到 manifest.config.ts 里的 h5.router.base
|
||||
VITE_APP_PUBLIC_BASE=/yskj/
|
||||
|
||||
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
|
||||
VITE_SERVER_BASEURL = 'http://localhost:8080/api'
|
||||
VITE_UPLOAD_BASEURL = 'https://ukw0y1.laf.run/upload'
|
||||
|
||||
VITE_STATIC_BASEURL = 'http://localhost:8080/'
|
||||
|
||||
# h5是否需要配置代理
|
||||
VITE_APP_PROXY=false
|
||||
VITE_APP_PROXY_PREFIX = '/api'
|
||||
|
@ -35,8 +35,8 @@ export default defineUniPages({
|
||||
{
|
||||
iconPath: 'static/tabbar/example.png',
|
||||
selectedIconPath: 'static/tabbar/exampleHL.png',
|
||||
pagePath: 'pages/about/about',
|
||||
text: '关于',
|
||||
pagePath: 'pages/shop/index',
|
||||
text: '商城',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
7
server/mall/.env.example
Normal file
7
server/mall/.env.example
Normal file
@ -0,0 +1,7 @@
|
||||
HOST=0.0.0.0
|
||||
PORT=8080
|
||||
APP_KEYS="toBeModified1,toBeModified2"
|
||||
API_TOKEN_SALT=tobemodified
|
||||
ADMIN_JWT_SECRET=tobemodified
|
||||
TRANSFER_TOKEN_SALT=tobemodified
|
||||
JWT_SECRET=tobemodified
|
131
server/mall/.gitignore
vendored
Normal file
131
server/mall/.gitignore
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
.tmp
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.idea
|
||||
nbproject
|
||||
public/uploads/*
|
||||
!public/uploads/.gitkeep
|
||||
.tsbuildinfo
|
||||
.eslintcache
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
node_modules
|
||||
.node_history
|
||||
|
||||
############################
|
||||
# Package managers
|
||||
############################
|
||||
|
||||
.yarn/*
|
||||
!.yarn/cache
|
||||
!.yarn/unplugged
|
||||
!.yarn/patches
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
.pnp.*
|
||||
yarn-error.log
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
coverage
|
||||
|
||||
############################
|
||||
# Strapi
|
||||
############################
|
||||
|
||||
.env
|
||||
license.txt
|
||||
exports
|
||||
.strapi
|
||||
dist
|
||||
build
|
||||
.strapi-updater.json
|
||||
.strapi-cloud.json
|
61
server/mall/README.md
Normal file
61
server/mall/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# 🚀 Getting started with Strapi
|
||||
|
||||
Strapi comes with a full featured [Command Line Interface](https://docs.strapi.io/dev-docs/cli) (CLI) which lets you scaffold and manage your project in seconds.
|
||||
|
||||
### `develop`
|
||||
|
||||
Start your Strapi application with autoReload enabled. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-develop)
|
||||
|
||||
```
|
||||
npm run develop
|
||||
# or
|
||||
yarn develop
|
||||
```
|
||||
|
||||
### `start`
|
||||
|
||||
Start your Strapi application with autoReload disabled. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-start)
|
||||
|
||||
```
|
||||
npm run start
|
||||
# or
|
||||
yarn start
|
||||
```
|
||||
|
||||
### `build`
|
||||
|
||||
Build your admin panel. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-build)
|
||||
|
||||
```
|
||||
npm run build
|
||||
# or
|
||||
yarn build
|
||||
```
|
||||
|
||||
## ⚙️ Deployment
|
||||
|
||||
Strapi gives you many possible deployment options for your project including [Strapi Cloud](https://cloud.strapi.io). Browse the [deployment section of the documentation](https://docs.strapi.io/dev-docs/deployment) to find the best solution for your use case.
|
||||
|
||||
```
|
||||
yarn strapi deploy
|
||||
```
|
||||
|
||||
## 📚 Learn more
|
||||
|
||||
- [Resource center](https://strapi.io/resource-center) - Strapi resource center.
|
||||
- [Strapi documentation](https://docs.strapi.io) - Official Strapi documentation.
|
||||
- [Strapi tutorials](https://strapi.io/tutorials) - List of tutorials made by the core team and the community.
|
||||
- [Strapi blog](https://strapi.io/blog) - Official Strapi blog containing articles made by the Strapi team and the community.
|
||||
- [Changelog](https://strapi.io/changelog) - Find out about the Strapi product updates, new features and general improvements.
|
||||
|
||||
Feel free to check out the [Strapi GitHub repository](https://github.com/strapi/strapi). Your feedback and contributions are welcome!
|
||||
|
||||
## ✨ Community
|
||||
|
||||
- [Discord](https://discord.strapi.io) - Come chat with the Strapi community including the core team.
|
||||
- [Forum](https://forum.strapi.io/) - Place to discuss, ask questions and find answers, show your Strapi project and get feedback or just talk with other Community members.
|
||||
- [Awesome Strapi](https://github.com/strapi/awesome-strapi) - A curated list of awesome things related to Strapi.
|
||||
|
||||
---
|
||||
|
||||
<sub>🤫 Psst! [Strapi is hiring](https://strapi.io/careers).</sub>
|
17
server/mall/config/admin.ts
Normal file
17
server/mall/config/admin.ts
Normal file
@ -0,0 +1,17 @@
|
||||
export default ({ env }) => ({
|
||||
auth: {
|
||||
secret: env('ADMIN_JWT_SECRET'),
|
||||
},
|
||||
apiToken: {
|
||||
salt: env('API_TOKEN_SALT'),
|
||||
},
|
||||
transfer: {
|
||||
token: {
|
||||
salt: env('TRANSFER_TOKEN_SALT'),
|
||||
},
|
||||
},
|
||||
flags: {
|
||||
nps: env.bool('FLAG_NPS', true),
|
||||
promoteEE: env.bool('FLAG_PROMOTE_EE', true),
|
||||
},
|
||||
});
|
7
server/mall/config/api.ts
Normal file
7
server/mall/config/api.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export default {
|
||||
rest: {
|
||||
defaultLimit: 25,
|
||||
maxLimit: 100,
|
||||
withCount: true,
|
||||
},
|
||||
};
|
60
server/mall/config/database.ts
Normal file
60
server/mall/config/database.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import path from 'path';
|
||||
|
||||
export default ({ env }) => {
|
||||
const client = env('DATABASE_CLIENT', 'sqlite');
|
||||
|
||||
const connections = {
|
||||
mysql: {
|
||||
connection: {
|
||||
host: env('DATABASE_HOST', 'localhost'),
|
||||
port: env.int('DATABASE_PORT', 3306),
|
||||
database: env('DATABASE_NAME', 'strapi'),
|
||||
user: env('DATABASE_USERNAME', 'strapi'),
|
||||
password: env('DATABASE_PASSWORD', 'strapi'),
|
||||
ssl: env.bool('DATABASE_SSL', false) && {
|
||||
key: env('DATABASE_SSL_KEY', undefined),
|
||||
cert: env('DATABASE_SSL_CERT', undefined),
|
||||
ca: env('DATABASE_SSL_CA', undefined),
|
||||
capath: env('DATABASE_SSL_CAPATH', undefined),
|
||||
cipher: env('DATABASE_SSL_CIPHER', undefined),
|
||||
rejectUnauthorized: env.bool('DATABASE_SSL_REJECT_UNAUTHORIZED', true),
|
||||
},
|
||||
},
|
||||
pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
|
||||
},
|
||||
postgres: {
|
||||
connection: {
|
||||
connectionString: env('DATABASE_URL'),
|
||||
host: env('DATABASE_HOST', 'localhost'),
|
||||
port: env.int('DATABASE_PORT', 5432),
|
||||
database: env('DATABASE_NAME', 'strapi'),
|
||||
user: env('DATABASE_USERNAME', 'strapi'),
|
||||
password: env('DATABASE_PASSWORD', 'strapi'),
|
||||
ssl: env.bool('DATABASE_SSL', false) && {
|
||||
key: env('DATABASE_SSL_KEY', undefined),
|
||||
cert: env('DATABASE_SSL_CERT', undefined),
|
||||
ca: env('DATABASE_SSL_CA', undefined),
|
||||
capath: env('DATABASE_SSL_CAPATH', undefined),
|
||||
cipher: env('DATABASE_SSL_CIPHER', undefined),
|
||||
rejectUnauthorized: env.bool('DATABASE_SSL_REJECT_UNAUTHORIZED', true),
|
||||
},
|
||||
schema: env('DATABASE_SCHEMA', 'public'),
|
||||
},
|
||||
pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
|
||||
},
|
||||
sqlite: {
|
||||
connection: {
|
||||
filename: path.join(__dirname, '..', '..', env('DATABASE_FILENAME', '.tmp/data.db')),
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
connection: {
|
||||
client,
|
||||
...connections[client],
|
||||
acquireConnectionTimeout: env.int('DATABASE_CONNECTION_TIMEOUT', 60000),
|
||||
},
|
||||
};
|
||||
};
|
12
server/mall/config/middlewares.ts
Normal file
12
server/mall/config/middlewares.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export default [
|
||||
'strapi::logger',
|
||||
'strapi::errors',
|
||||
'strapi::security',
|
||||
'strapi::cors',
|
||||
'strapi::poweredBy',
|
||||
'strapi::query',
|
||||
'strapi::body',
|
||||
'strapi::session',
|
||||
'strapi::favicon',
|
||||
'strapi::public',
|
||||
];
|
1
server/mall/config/plugins.ts
Normal file
1
server/mall/config/plugins.ts
Normal file
@ -0,0 +1 @@
|
||||
export default () => ({});
|
7
server/mall/config/server.ts
Normal file
7
server/mall/config/server.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export default ({ env }) => ({
|
||||
host: env('HOST', '0.0.0.0'),
|
||||
port: env.int('PORT', 1337),
|
||||
app: {
|
||||
keys: env.array('APP_KEYS'),
|
||||
},
|
||||
});
|
0
server/mall/database/migrations/.gitkeep
Normal file
0
server/mall/database/migrations/.gitkeep
Normal file
BIN
server/mall/favicon.png
Normal file
BIN
server/mall/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 497 B |
18734
server/mall/package-lock.json
generated
Normal file
18734
server/mall/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
37
server/mall/package.json
Normal file
37
server/mall/package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "mall",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "A Strapi application",
|
||||
"scripts": {
|
||||
"build": "strapi build",
|
||||
"deploy": "strapi deploy",
|
||||
"develop": "strapi develop",
|
||||
"start": "strapi start",
|
||||
"strapi": "strapi"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/plugin-cloud": "5.0.5",
|
||||
"@strapi/plugin-color-picker": "^5.0.5",
|
||||
"@strapi/plugin-users-permissions": "5.0.5",
|
||||
"@strapi/strapi": "5.0.5",
|
||||
"better-sqlite3": "11.3.0",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-router-dom": "^6.0.0",
|
||||
"styled-components": "^6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <=22.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"strapi": {
|
||||
"uuid": "ff207221-3a78-479c-83e0-36bb841142ce"
|
||||
}
|
||||
}
|
3
server/mall/public/robots.txt
Normal file
3
server/mall/public/robots.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# To prevent search engines from seeing the site altogether, uncomment the next two lines:
|
||||
# User-Agent: *
|
||||
# Disallow: /
|
0
server/mall/public/uploads/.gitkeep
Normal file
0
server/mall/public/uploads/.gitkeep
Normal file
37
server/mall/src/admin/app.example.tsx
Normal file
37
server/mall/src/admin/app.example.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import type { StrapiApp } from '@strapi/strapi/admin';
|
||||
|
||||
export default {
|
||||
config: {
|
||||
locales: [
|
||||
// 'ar',
|
||||
// 'fr',
|
||||
// 'cs',
|
||||
// 'de',
|
||||
// 'dk',
|
||||
// 'es',
|
||||
// 'he',
|
||||
// 'id',
|
||||
// 'it',
|
||||
// 'ja',
|
||||
// 'ko',
|
||||
// 'ms',
|
||||
// 'nl',
|
||||
// 'no',
|
||||
// 'pl',
|
||||
// 'pt-BR',
|
||||
// 'pt',
|
||||
// 'ru',
|
||||
// 'sk',
|
||||
// 'sv',
|
||||
// 'th',
|
||||
// 'tr',
|
||||
// 'uk',
|
||||
// 'vi',
|
||||
// 'zh-Hans',
|
||||
// 'zh',
|
||||
],
|
||||
},
|
||||
bootstrap(app: StrapiApp) {
|
||||
console.log(app);
|
||||
},
|
||||
};
|
15
server/mall/src/admin/app.js
Normal file
15
server/mall/src/admin/app.js
Normal file
@ -0,0 +1,15 @@
|
||||
export default {
|
||||
config: {
|
||||
locales: ['zh-Hans'],
|
||||
translations: {
|
||||
'zh-Hans': {
|
||||
'Auth.form.email.label': '1471299010@qq.com',
|
||||
Users: '1471299010@qq.com',
|
||||
City: 'Chinese (Simplified) (zh-Hans)',
|
||||
// 这里是刚刚在设置中新建的国际化语言版本的ID
|
||||
Id: '3',
|
||||
},
|
||||
},
|
||||
},
|
||||
bootstrap() { },
|
||||
}
|
20
server/mall/src/admin/tsconfig.json
Normal file
20
server/mall/src/admin/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["../plugins/**/admin/src/**/*", "./"],
|
||||
"exclude": ["node_modules/", "build/", "dist/", "**/*.test.ts"]
|
||||
}
|
12
server/mall/src/admin/vite.config.example.ts
Normal file
12
server/mall/src/admin/vite.config.example.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { mergeConfig, type UserConfig } from 'vite';
|
||||
|
||||
export default (config: UserConfig) => {
|
||||
// Important: always return the modified config
|
||||
return mergeConfig(config, {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': '/src',
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
0
server/mall/src/api/.gitkeep
Normal file
0
server/mall/src/api/.gitkeep
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "categorys",
|
||||
"info": {
|
||||
"singularName": "category",
|
||||
"pluralName": "categorys",
|
||||
"displayName": "分类",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"categoryName": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"unique": true
|
||||
},
|
||||
"icon": {
|
||||
"type": "media",
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"allowedTypes": [
|
||||
"images",
|
||||
"files",
|
||||
"videos",
|
||||
"audios"
|
||||
]
|
||||
},
|
||||
"products": {
|
||||
"type": "relation",
|
||||
"relation": "manyToMany",
|
||||
"target": "api::product.product",
|
||||
"inversedBy": "categoryType"
|
||||
}
|
||||
}
|
||||
}
|
7
server/mall/src/api/category/controllers/category.ts
Normal file
7
server/mall/src/api/category/controllers/category.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* category controller
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi'
|
||||
|
||||
export default factories.createCoreController('api::category.category');
|
7
server/mall/src/api/category/routes/category.ts
Normal file
7
server/mall/src/api/category/routes/category.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* category router
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreRouter('api::category.category');
|
7
server/mall/src/api/category/services/category.ts
Normal file
7
server/mall/src/api/category/services/category.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* category service
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreService('api::category.category');
|
@ -0,0 +1,56 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "products",
|
||||
"info": {
|
||||
"singularName": "product",
|
||||
"pluralName": "products",
|
||||
"displayName": "商品",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "richtext"
|
||||
},
|
||||
"product_image": {
|
||||
"type": "media",
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"allowedTypes": [
|
||||
"images",
|
||||
"files",
|
||||
"videos",
|
||||
"audios"
|
||||
]
|
||||
},
|
||||
"categoryType": {
|
||||
"type": "relation",
|
||||
"relation": "manyToMany",
|
||||
"target": "api::category.category",
|
||||
"mappedBy": "products"
|
||||
},
|
||||
"product_images": {
|
||||
"type": "media",
|
||||
"multiple": true,
|
||||
"required": false,
|
||||
"allowedTypes": [
|
||||
"images",
|
||||
"files",
|
||||
"videos",
|
||||
"audios"
|
||||
]
|
||||
},
|
||||
"tags": {
|
||||
"type": "relation",
|
||||
"relation": "manyToMany",
|
||||
"target": "api::tag.tag",
|
||||
"inversedBy": "tagType"
|
||||
}
|
||||
}
|
||||
}
|
7
server/mall/src/api/product/controllers/product.ts
Normal file
7
server/mall/src/api/product/controllers/product.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* product controller
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi'
|
||||
|
||||
export default factories.createCoreController('api::product.product');
|
7
server/mall/src/api/product/routes/product.ts
Normal file
7
server/mall/src/api/product/routes/product.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* product router
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreRouter('api::product.product');
|
7
server/mall/src/api/product/services/product.ts
Normal file
7
server/mall/src/api/product/services/product.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* product service
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreService('api::product.product');
|
@ -0,0 +1,37 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "recommends",
|
||||
"info": {
|
||||
"singularName": "recommend",
|
||||
"pluralName": "recommends",
|
||||
"displayName": "推广"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"image": {
|
||||
"allowedTypes": [
|
||||
"images",
|
||||
"files",
|
||||
"videos",
|
||||
"audios"
|
||||
],
|
||||
"type": "media",
|
||||
"multiple": true
|
||||
},
|
||||
"is_on": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"products": {
|
||||
"type": "relation",
|
||||
"relation": "oneToMany",
|
||||
"target": "api::product.product"
|
||||
}
|
||||
}
|
||||
}
|
7
server/mall/src/api/recommend/controllers/recommend.ts
Normal file
7
server/mall/src/api/recommend/controllers/recommend.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* recommend controller
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi'
|
||||
|
||||
export default factories.createCoreController('api::recommend.recommend');
|
7
server/mall/src/api/recommend/routes/recommend.ts
Normal file
7
server/mall/src/api/recommend/routes/recommend.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* recommend router
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreRouter('api::recommend.recommend');
|
7
server/mall/src/api/recommend/services/recommend.ts
Normal file
7
server/mall/src/api/recommend/services/recommend.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* recommend service
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreService('api::recommend.recommend');
|
32
server/mall/src/api/tag/content-types/tag/schema.json
Normal file
32
server/mall/src/api/tag/content-types/tag/schema.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "tags",
|
||||
"info": {
|
||||
"singularName": "tag",
|
||||
"pluralName": "tags",
|
||||
"displayName": "标签"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"tag": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"unique": true
|
||||
},
|
||||
"color": {
|
||||
"type": "customField",
|
||||
"regex": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$",
|
||||
"customField": "plugin::color-picker.color",
|
||||
"required": true
|
||||
},
|
||||
"tagType": {
|
||||
"type": "relation",
|
||||
"relation": "manyToMany",
|
||||
"target": "api::product.product",
|
||||
"mappedBy": "tags"
|
||||
}
|
||||
}
|
||||
}
|
7
server/mall/src/api/tag/controllers/tag.ts
Normal file
7
server/mall/src/api/tag/controllers/tag.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* tag controller
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi'
|
||||
|
||||
export default factories.createCoreController('api::tag.tag');
|
7
server/mall/src/api/tag/routes/tag.ts
Normal file
7
server/mall/src/api/tag/routes/tag.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* tag router
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreRouter('api::tag.tag');
|
7
server/mall/src/api/tag/services/tag.ts
Normal file
7
server/mall/src/api/tag/services/tag.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* tag service
|
||||
*/
|
||||
|
||||
import { factories } from '@strapi/strapi';
|
||||
|
||||
export default factories.createCoreService('api::tag.tag');
|
19
server/mall/src/components/field/promotion-component.json
Normal file
19
server/mall/src/components/field/promotion-component.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"collectionName": "components_field_promotion_components",
|
||||
"info": {
|
||||
"displayName": "PromotionComponent"
|
||||
},
|
||||
"options": {},
|
||||
"attributes": {
|
||||
"img": {
|
||||
"allowedTypes": [
|
||||
"images",
|
||||
"files",
|
||||
"videos",
|
||||
"audios"
|
||||
],
|
||||
"type": "media",
|
||||
"multiple": false
|
||||
}
|
||||
}
|
||||
}
|
0
server/mall/src/extensions/.gitkeep
Normal file
0
server/mall/src/extensions/.gitkeep
Normal file
20
server/mall/src/index.ts
Normal file
20
server/mall/src/index.ts
Normal file
@ -0,0 +1,20 @@
|
||||
// import type { Core } from '@strapi/strapi';
|
||||
|
||||
export default {
|
||||
/**
|
||||
* An asynchronous register function that runs before
|
||||
* your application is initialized.
|
||||
*
|
||||
* This gives you an opportunity to extend code.
|
||||
*/
|
||||
register(/* { strapi }: { strapi: Core.Strapi } */) {},
|
||||
|
||||
/**
|
||||
* An asynchronous bootstrap function that runs before
|
||||
* your application gets started.
|
||||
*
|
||||
* This gives you an opportunity to set up your data model,
|
||||
* run jobs, or perform some special logic.
|
||||
*/
|
||||
bootstrap(/* { strapi }: { strapi: Core.Strapi } */) {},
|
||||
};
|
43
server/mall/tsconfig.json
Normal file
43
server/mall/tsconfig.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "Node",
|
||||
"lib": ["ES2020"],
|
||||
"target": "ES2019",
|
||||
"strict": false,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"incremental": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"noEmitOnError": true,
|
||||
"noImplicitThis": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "."
|
||||
},
|
||||
"include": [
|
||||
// Include root files
|
||||
"./",
|
||||
// Include all ts files
|
||||
"./**/*.ts",
|
||||
// Include all js files
|
||||
"./**/*.js",
|
||||
// Force the JSON files in the src folder to be included
|
||||
"src/**/*.json"
|
||||
],
|
||||
|
||||
"exclude": [
|
||||
"node_modules/",
|
||||
"build/",
|
||||
"dist/",
|
||||
".cache/",
|
||||
".tmp/",
|
||||
|
||||
// Do not include admin files in the server compilation
|
||||
"src/admin/",
|
||||
// Do not include test files
|
||||
"**/*.test.*",
|
||||
// Do not include plugins in the server compilation
|
||||
"src/plugins/**"
|
||||
]
|
||||
}
|
19
server/mall/types/generated/components.d.ts
vendored
Normal file
19
server/mall/types/generated/components.d.ts
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
import type { Struct, Schema } from '@strapi/strapi'
|
||||
|
||||
export interface FieldPromotionComponent extends Struct.ComponentSchema {
|
||||
collectionName: 'components_field_promotion_components'
|
||||
info: {
|
||||
displayName: 'PromotionComponent'
|
||||
}
|
||||
attributes: {
|
||||
img: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@strapi/strapi' {
|
||||
export module Public {
|
||||
export interface ComponentSchemas {
|
||||
'field.promotion-component': FieldPromotionComponent
|
||||
}
|
||||
}
|
||||
}
|
859
server/mall/types/generated/contentTypes.d.ts
vendored
Normal file
859
server/mall/types/generated/contentTypes.d.ts
vendored
Normal file
@ -0,0 +1,859 @@
|
||||
import type { Struct, Schema } from '@strapi/strapi'
|
||||
|
||||
export interface PluginUploadFile extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'files'
|
||||
info: {
|
||||
singularName: 'file'
|
||||
pluralName: 'files'
|
||||
displayName: 'File'
|
||||
description: ''
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String & Schema.Attribute.Required
|
||||
alternativeText: Schema.Attribute.String
|
||||
caption: Schema.Attribute.String
|
||||
width: Schema.Attribute.Integer
|
||||
height: Schema.Attribute.Integer
|
||||
formats: Schema.Attribute.JSON
|
||||
hash: Schema.Attribute.String & Schema.Attribute.Required
|
||||
ext: Schema.Attribute.String
|
||||
mime: Schema.Attribute.String & Schema.Attribute.Required
|
||||
size: Schema.Attribute.Decimal & Schema.Attribute.Required
|
||||
url: Schema.Attribute.String & Schema.Attribute.Required
|
||||
previewUrl: Schema.Attribute.String
|
||||
provider: Schema.Attribute.String & Schema.Attribute.Required
|
||||
provider_metadata: Schema.Attribute.JSON
|
||||
related: Schema.Attribute.Relation<'morphToMany'>
|
||||
folder: Schema.Attribute.Relation<'manyToOne', 'plugin::upload.folder'> &
|
||||
Schema.Attribute.Private
|
||||
folderPath: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.Private &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.file'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginUploadFolder extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'upload_folders'
|
||||
info: {
|
||||
singularName: 'folder'
|
||||
pluralName: 'folders'
|
||||
displayName: 'Folder'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
pathId: Schema.Attribute.Integer & Schema.Attribute.Required & Schema.Attribute.Unique
|
||||
parent: Schema.Attribute.Relation<'manyToOne', 'plugin::upload.folder'>
|
||||
children: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.folder'>
|
||||
files: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.file'>
|
||||
path: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::upload.folder'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginI18NLocale extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'i18n_locale'
|
||||
info: {
|
||||
singularName: 'locale'
|
||||
pluralName: 'locales'
|
||||
collectionName: 'locales'
|
||||
displayName: 'Locale'
|
||||
description: ''
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String &
|
||||
Schema.Attribute.SetMinMax<
|
||||
{
|
||||
min: 1
|
||||
max: 50
|
||||
},
|
||||
number
|
||||
>
|
||||
code: Schema.Attribute.String & Schema.Attribute.Unique
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::i18n.locale'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginContentReleasesRelease extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'strapi_releases'
|
||||
info: {
|
||||
singularName: 'release'
|
||||
pluralName: 'releases'
|
||||
displayName: 'Release'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String & Schema.Attribute.Required
|
||||
releasedAt: Schema.Attribute.DateTime
|
||||
scheduledAt: Schema.Attribute.DateTime
|
||||
timezone: Schema.Attribute.String
|
||||
status: Schema.Attribute.Enumeration<['ready', 'blocked', 'failed', 'done', 'empty']> &
|
||||
Schema.Attribute.Required
|
||||
actions: Schema.Attribute.Relation<'oneToMany', 'plugin::content-releases.release-action'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::content-releases.release'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginContentReleasesReleaseAction extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'strapi_release_actions'
|
||||
info: {
|
||||
singularName: 'release-action'
|
||||
pluralName: 'release-actions'
|
||||
displayName: 'Release Action'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
type: Schema.Attribute.Enumeration<['publish', 'unpublish']> & Schema.Attribute.Required
|
||||
contentType: Schema.Attribute.String & Schema.Attribute.Required
|
||||
entryDocumentId: Schema.Attribute.String
|
||||
locale: Schema.Attribute.String
|
||||
release: Schema.Attribute.Relation<'manyToOne', 'plugin::content-releases.release'>
|
||||
isEntryValid: Schema.Attribute.Boolean
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::content-releases.release-action'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginReviewWorkflowsWorkflow extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'strapi_workflows'
|
||||
info: {
|
||||
name: 'Workflow'
|
||||
description: ''
|
||||
singularName: 'workflow'
|
||||
pluralName: 'workflows'
|
||||
displayName: 'Workflow'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique
|
||||
stages: Schema.Attribute.Relation<'oneToMany', 'plugin::review-workflows.workflow-stage'>
|
||||
contentTypes: Schema.Attribute.JSON &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.DefaultTo<'[]'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::review-workflows.workflow'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginReviewWorkflowsWorkflowStage extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'strapi_workflows_stages'
|
||||
info: {
|
||||
name: 'Workflow Stage'
|
||||
description: ''
|
||||
singularName: 'workflow-stage'
|
||||
pluralName: 'workflow-stages'
|
||||
displayName: 'Stages'
|
||||
}
|
||||
options: {
|
||||
version: '1.1.0'
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String
|
||||
color: Schema.Attribute.String & Schema.Attribute.DefaultTo<'#4945FF'>
|
||||
workflow: Schema.Attribute.Relation<'manyToOne', 'plugin::review-workflows.workflow'>
|
||||
permissions: Schema.Attribute.Relation<'manyToMany', 'admin::permission'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::review-workflows.workflow-stage'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginUsersPermissionsPermission extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'up_permissions'
|
||||
info: {
|
||||
name: 'permission'
|
||||
description: ''
|
||||
singularName: 'permission'
|
||||
pluralName: 'permissions'
|
||||
displayName: 'Permission'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
action: Schema.Attribute.String & Schema.Attribute.Required
|
||||
role: Schema.Attribute.Relation<'manyToOne', 'plugin::users-permissions.role'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.permission'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginUsersPermissionsRole extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'up_roles'
|
||||
info: {
|
||||
name: 'role'
|
||||
description: ''
|
||||
singularName: 'role'
|
||||
pluralName: 'roles'
|
||||
displayName: 'Role'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 3
|
||||
}>
|
||||
description: Schema.Attribute.String
|
||||
type: Schema.Attribute.String & Schema.Attribute.Unique
|
||||
permissions: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.permission'>
|
||||
users: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.user'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.role'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginUsersPermissionsUser extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'up_users'
|
||||
info: {
|
||||
name: 'user'
|
||||
description: ''
|
||||
singularName: 'user'
|
||||
pluralName: 'users'
|
||||
displayName: 'User'
|
||||
}
|
||||
options: {
|
||||
timestamps: true
|
||||
draftAndPublish: false
|
||||
}
|
||||
attributes: {
|
||||
username: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.Unique &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 3
|
||||
}>
|
||||
email: Schema.Attribute.Email &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 6
|
||||
}>
|
||||
provider: Schema.Attribute.String
|
||||
password: Schema.Attribute.Password &
|
||||
Schema.Attribute.Private &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 6
|
||||
}>
|
||||
resetPasswordToken: Schema.Attribute.String & Schema.Attribute.Private
|
||||
confirmationToken: Schema.Attribute.String & Schema.Attribute.Private
|
||||
confirmed: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>
|
||||
blocked: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>
|
||||
role: Schema.Attribute.Relation<'manyToOne', 'plugin::users-permissions.role'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'plugin::users-permissions.user'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ApiCategoryCategory extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'categorys'
|
||||
info: {
|
||||
singularName: 'category'
|
||||
pluralName: 'categorys'
|
||||
displayName: '\u5206\u7C7B'
|
||||
description: ''
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: true
|
||||
}
|
||||
attributes: {
|
||||
categoryName: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique
|
||||
icon: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>
|
||||
products: Schema.Attribute.Relation<'manyToMany', 'api::product.product'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'api::category.category'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ApiProductProduct extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'products'
|
||||
info: {
|
||||
singularName: 'product'
|
||||
pluralName: 'products'
|
||||
displayName: '\u5546\u54C1'
|
||||
description: ''
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: true
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String
|
||||
description: Schema.Attribute.RichText
|
||||
product_image: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'>
|
||||
categoryType: Schema.Attribute.Relation<'manyToMany', 'api::category.category'>
|
||||
product_images: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios', true>
|
||||
tags: Schema.Attribute.Relation<'manyToMany', 'api::tag.tag'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'api::product.product'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ApiRecommendRecommend extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'recommends'
|
||||
info: {
|
||||
singularName: 'recommend'
|
||||
pluralName: 'recommends'
|
||||
displayName: '\u63A8\u5E7F'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: true
|
||||
}
|
||||
attributes: {
|
||||
title: Schema.Attribute.String
|
||||
image: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios', true>
|
||||
is_on: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<true>
|
||||
products: Schema.Attribute.Relation<'oneToMany', 'api::product.product'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'api::recommend.recommend'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ApiTagTag extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'tags'
|
||||
info: {
|
||||
singularName: 'tag'
|
||||
pluralName: 'tags'
|
||||
displayName: '\u6807\u7B7E'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: true
|
||||
}
|
||||
attributes: {
|
||||
tag: Schema.Attribute.String & Schema.Attribute.Required & Schema.Attribute.Unique
|
||||
color: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.CustomField<'plugin::color-picker.color'>
|
||||
tagType: Schema.Attribute.Relation<'manyToMany', 'api::product.product'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'api::tag.tag'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface AdminPermission extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'admin_permissions'
|
||||
info: {
|
||||
name: 'Permission'
|
||||
description: ''
|
||||
singularName: 'permission'
|
||||
pluralName: 'permissions'
|
||||
displayName: 'Permission'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
action: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
actionParameters: Schema.Attribute.JSON & Schema.Attribute.DefaultTo<{}>
|
||||
subject: Schema.Attribute.String &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
properties: Schema.Attribute.JSON & Schema.Attribute.DefaultTo<{}>
|
||||
conditions: Schema.Attribute.JSON & Schema.Attribute.DefaultTo<[]>
|
||||
role: Schema.Attribute.Relation<'manyToOne', 'admin::role'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::permission'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface AdminUser extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'admin_users'
|
||||
info: {
|
||||
name: 'User'
|
||||
description: ''
|
||||
singularName: 'user'
|
||||
pluralName: 'users'
|
||||
displayName: 'User'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
firstname: Schema.Attribute.String &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
lastname: Schema.Attribute.String &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
username: Schema.Attribute.String
|
||||
email: Schema.Attribute.Email &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.Private &
|
||||
Schema.Attribute.Unique &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 6
|
||||
}>
|
||||
password: Schema.Attribute.Password &
|
||||
Schema.Attribute.Private &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 6
|
||||
}>
|
||||
resetPasswordToken: Schema.Attribute.String & Schema.Attribute.Private
|
||||
registrationToken: Schema.Attribute.String & Schema.Attribute.Private
|
||||
isActive: Schema.Attribute.Boolean &
|
||||
Schema.Attribute.Private &
|
||||
Schema.Attribute.DefaultTo<false>
|
||||
roles: Schema.Attribute.Relation<'manyToMany', 'admin::role'> & Schema.Attribute.Private
|
||||
blocked: Schema.Attribute.Boolean & Schema.Attribute.Private & Schema.Attribute.DefaultTo<false>
|
||||
preferedLanguage: Schema.Attribute.String
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::user'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface AdminRole extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'admin_roles'
|
||||
info: {
|
||||
name: 'Role'
|
||||
description: ''
|
||||
singularName: 'role'
|
||||
pluralName: 'roles'
|
||||
displayName: 'Role'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.Unique &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
code: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.Unique &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
description: Schema.Attribute.String
|
||||
users: Schema.Attribute.Relation<'manyToMany', 'admin::user'>
|
||||
permissions: Schema.Attribute.Relation<'oneToMany', 'admin::permission'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::role'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface AdminApiToken extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'strapi_api_tokens'
|
||||
info: {
|
||||
name: 'Api Token'
|
||||
singularName: 'api-token'
|
||||
pluralName: 'api-tokens'
|
||||
displayName: 'Api Token'
|
||||
description: ''
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.Unique &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
description: Schema.Attribute.String &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}> &
|
||||
Schema.Attribute.DefaultTo<''>
|
||||
type: Schema.Attribute.Enumeration<['read-only', 'full-access', 'custom']> &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.DefaultTo<'read-only'>
|
||||
accessKey: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
lastUsedAt: Schema.Attribute.DateTime
|
||||
permissions: Schema.Attribute.Relation<'oneToMany', 'admin::api-token-permission'>
|
||||
expiresAt: Schema.Attribute.DateTime
|
||||
lifespan: Schema.Attribute.BigInteger
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::api-token'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface AdminApiTokenPermission extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'strapi_api_token_permissions'
|
||||
info: {
|
||||
name: 'API Token Permission'
|
||||
description: ''
|
||||
singularName: 'api-token-permission'
|
||||
pluralName: 'api-token-permissions'
|
||||
displayName: 'API Token Permission'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
action: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
token: Schema.Attribute.Relation<'manyToOne', 'admin::api-token'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::api-token-permission'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface AdminTransferToken extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'strapi_transfer_tokens'
|
||||
info: {
|
||||
name: 'Transfer Token'
|
||||
singularName: 'transfer-token'
|
||||
pluralName: 'transfer-tokens'
|
||||
displayName: 'Transfer Token'
|
||||
description: ''
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
name: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.Unique &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
description: Schema.Attribute.String &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}> &
|
||||
Schema.Attribute.DefaultTo<''>
|
||||
accessKey: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
lastUsedAt: Schema.Attribute.DateTime
|
||||
permissions: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token-permission'>
|
||||
expiresAt: Schema.Attribute.DateTime
|
||||
lifespan: Schema.Attribute.BigInteger
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token'>
|
||||
}
|
||||
}
|
||||
|
||||
export interface AdminTransferTokenPermission extends Struct.CollectionTypeSchema {
|
||||
collectionName: 'strapi_transfer_token_permissions'
|
||||
info: {
|
||||
name: 'Transfer Token Permission'
|
||||
description: ''
|
||||
singularName: 'transfer-token-permission'
|
||||
pluralName: 'transfer-token-permissions'
|
||||
displayName: 'Transfer Token Permission'
|
||||
}
|
||||
options: {
|
||||
draftAndPublish: false
|
||||
}
|
||||
pluginOptions: {
|
||||
'content-manager': {
|
||||
visible: false
|
||||
}
|
||||
'content-type-builder': {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
attributes: {
|
||||
action: Schema.Attribute.String &
|
||||
Schema.Attribute.Required &
|
||||
Schema.Attribute.SetMinMaxLength<{
|
||||
minLength: 1
|
||||
}>
|
||||
token: Schema.Attribute.Relation<'manyToOne', 'admin::transfer-token'>
|
||||
createdAt: Schema.Attribute.DateTime
|
||||
updatedAt: Schema.Attribute.DateTime
|
||||
publishedAt: Schema.Attribute.DateTime
|
||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private
|
||||
locale: Schema.Attribute.String
|
||||
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::transfer-token-permission'>
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@strapi/strapi' {
|
||||
export module Public {
|
||||
export interface ContentTypeSchemas {
|
||||
'plugin::upload.file': PluginUploadFile
|
||||
'plugin::upload.folder': PluginUploadFolder
|
||||
'plugin::i18n.locale': PluginI18NLocale
|
||||
'plugin::content-releases.release': PluginContentReleasesRelease
|
||||
'plugin::content-releases.release-action': PluginContentReleasesReleaseAction
|
||||
'plugin::review-workflows.workflow': PluginReviewWorkflowsWorkflow
|
||||
'plugin::review-workflows.workflow-stage': PluginReviewWorkflowsWorkflowStage
|
||||
'plugin::users-permissions.permission': PluginUsersPermissionsPermission
|
||||
'plugin::users-permissions.role': PluginUsersPermissionsRole
|
||||
'plugin::users-permissions.user': PluginUsersPermissionsUser
|
||||
'api::category.category': ApiCategoryCategory
|
||||
'api::product.product': ApiProductProduct
|
||||
'api::recommend.recommend': ApiRecommendRecommend
|
||||
'api::tag.tag': ApiTagTag
|
||||
'admin::permission': AdminPermission
|
||||
'admin::user': AdminUser
|
||||
'admin::role': AdminRole
|
||||
'admin::api-token': AdminApiToken
|
||||
'admin::api-token-permission': AdminApiTokenPermission
|
||||
'admin::transfer-token': AdminTransferToken
|
||||
'admin::transfer-token-permission': AdminTransferTokenPermission
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ onLaunch(() => {
|
||||
console.log('App Launch')
|
||||
})
|
||||
onShow(() => {
|
||||
// 隐藏底部tabbar
|
||||
uni.hideTabBar()
|
||||
console.log('App Show')
|
||||
})
|
||||
onHide(() => {
|
||||
|
7
src/components/goods.vue
Normal file
7
src/components/goods.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<view class=""></view>
|
||||
</template>
|
||||
|
||||
<script lang="js" setup></script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
56
src/components/tabbar.vue
Normal file
56
src/components/tabbar.vue
Normal file
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<view
|
||||
class="tab-bar flex justify-around bg-white border-t border-gray-200 pos-fixed bottom-0 w-full"
|
||||
>
|
||||
<view
|
||||
v-for="(item, index) in tabs"
|
||||
:key="index"
|
||||
class="tab-item flex-1 flex flex-col items-center justify-center py-2 cursor-pointer"
|
||||
@click="selectTab(item, index)"
|
||||
:class="{ active: item.path === routers.routers.path }"
|
||||
>
|
||||
<view class="icon-wrapper relative w-6 h-6 mb-1">
|
||||
<view
|
||||
class="icon-svg relative z-10 w-6 h-6"
|
||||
v-html="item.path === routers.routers.path ? item.activeIcon : item.icon"
|
||||
></view>
|
||||
</view>
|
||||
<text
|
||||
class="text text-xs text-center"
|
||||
:class="{
|
||||
'text-[#00a2ff]': item.path === routers.routers.path,
|
||||
'text-gray-800': item.path !== routers.routers.path,
|
||||
}"
|
||||
>
|
||||
{{ item.text }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useRouterStore } from '@/store/routers'
|
||||
|
||||
const routers = useRouterStore()
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
text: '首页',
|
||||
path: '/pages/index/index',
|
||||
icon: `<svg t="1728621030479" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3744" width="24" height="24"><path d="M972.631118 255.850987L565.400878 14.630378C548.928157 4.876793 530.468594 0 511.990969 0s-36.937188 4.876793-53.391847 14.630378L51.368882 255.850987A104.796853 104.796853 0 0 0 0 345.9994v573.239871c0 57.853209 46.907519 104.760729 104.760729 104.760729h814.46048c57.853209 0 104.760729-46.907519 104.760729-104.760729V345.9994a104.74086 104.74086 0 0 0-51.35082-90.148413zM950.071437 882.067275c0 37.569365-30.45286 68.022225-68.022225 68.022225H141.932725c-37.569365 0-68.022225-30.45286-68.022225-68.022225V360.774275a56.769478 56.769478 0 0 1 27.851905-48.858236L496.27686 78.227365c4.750357-2.817702 10.187078-4.298802 15.714109-4.298802 5.527032 0 10.963752 1.4811 15.714109 4.298802l394.514455 233.688674a56.791152 56.791152 0 0 1 27.833842 48.858236v521.293z" p-id="3745"></path></svg>`,
|
||||
activeIcon: `<svg t="1728621030479" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3744" width="24" height="24"><path d="M972.631118 255.850987L565.400878 14.630378C548.928157 4.876793 530.468594 0 511.990969 0s-36.937188 4.876793-53.391847 14.630378L51.368882 255.850987A104.796853 104.796853 0 0 0 0 345.9994v573.239871c0 57.853209 46.907519 104.760729 104.760729 104.760729h814.46048c57.853209 0 104.760729-46.907519 104.760729-104.760729V345.9994a104.74086 104.74086 0 0 0-51.35082-90.148413zM950.071437 882.067275c0 37.569365-30.45286 68.022225-68.022225 68.022225H141.932725c-37.569365 0-68.022225-30.45286-68.022225-68.022225V360.774275a56.769478 56.769478 0 0 1 27.851905-48.858236L496.27686 78.227365c4.750357-2.817702 10.187078-4.298802 15.714109-4.298802 5.527032 0 10.963752 1.4811 15.714109 4.298802l394.514455 233.688674a56.791152 56.791152 0 0 1 27.833842 48.858236v521.293z" p-id="3745" fill="#00A2FF"></path></svg>`,
|
||||
},
|
||||
{
|
||||
text: '商城',
|
||||
path: '/pages/shop/index',
|
||||
icon: `<svg t="1728621083153" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4786" width="24" height="24"><path d="M825.6 554.666667c-64 0-121.6-38.4-155.733333-89.6C633.6 516.266667 576 554.666667 512 554.666667s-121.6-38.4-155.733333-89.6C320 516.266667 264.533333 554.666667 198.4 554.666667 89.6 554.666667 0 465.066667 0 356.266667v-8.533334L151.466667 0h721.066666L1024 345.6v8.533333c0 110.933333-89.6 200.533333-198.4 200.533334z m-200.533333-219.733334h85.333333c0 61.866667 51.2 134.4 113.066667 134.4 59.733333 0 108.8-46.933333 113.066666-104.533333L817.066667 85.333333H206.933333L85.333333 364.8c4.266667 57.6 53.333333 104.533333 113.066667 104.533333 64 0 113.066667-74.666667 113.066667-134.4h85.333333c0 61.866667 51.2 134.4 113.066667 134.4 66.133333 0 115.2-74.666667 115.2-134.4zM810.666667 1021.866667H213.333333c-83.2 0-149.333333-64-149.333333-142.933334V595.2h85.333333v283.733333c0 32 27.733333 57.6 64 57.6h597.333334c34.133333 0 64-25.6 64-57.6V595.2h85.333333v283.733333c0 78.933333-66.133333 142.933333-149.333333 142.933334z" p-id="4787"></path></svg>`,
|
||||
activeIcon: `<svg t="1728621083153" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4786" width="24" height="24"><path d="M825.6 554.666667c-64 0-121.6-38.4-155.733333-89.6C633.6 516.266667 576 554.666667 512 554.666667s-121.6-38.4-155.733333-89.6C320 516.266667 264.533333 554.666667 198.4 554.666667 89.6 554.666667 0 465.066667 0 356.266667v-8.533334L151.466667 0h721.066666L1024 345.6v8.533333c0 110.933333-89.6 200.533333-198.4 200.533334z m-200.533333-219.733334h85.333333c0 61.866667 51.2 134.4 113.066667 134.4 59.733333 0 108.8-46.933333 113.066666-104.533333L817.066667 85.333333H206.933333L85.333333 364.8c4.266667 57.6 53.333333 104.533333 113.066667 104.533333 64 0 113.066667-74.666667 113.066667-134.4h85.333333c0 61.866667 51.2 134.4 113.066667 134.4 66.133333 0 115.2-74.666667 115.2-134.4zM810.666667 1021.866667H213.333333c-83.2 0-149.333333-64-149.333333-142.933334V595.2h85.333333v283.733333c0 32 27.733333 57.6 64 57.6h597.333334c34.133333 0 64-25.6 64-57.6V595.2h85.333333v283.733333c0 78.933333-66.133333 142.933333-149.333333 142.933334z" p-id="4787" fill="#00A2FF"></path></svg>`,
|
||||
},
|
||||
]
|
||||
|
||||
const selectTab = (tab, index) => {
|
||||
uni.switchTab({ url: tab.path })
|
||||
routers.routers.path = tab.path
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@ -32,8 +32,8 @@
|
||||
{
|
||||
"iconPath": "static/tabbar/example.png",
|
||||
"selectedIconPath": "static/tabbar/exampleHL.png",
|
||||
"pagePath": "pages/about/about",
|
||||
"text": "关于"
|
||||
"pagePath": "pages/shop/index",
|
||||
"text": "商城"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -47,10 +47,27 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/about/about",
|
||||
"path": "pages/product/index",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationBarTitleText": "商城"
|
||||
"navigationBarTitleText": "商品详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/search/index",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationBarTitleText": "搜索页面"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/shop/index",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationBarTitleText": "宇森科技软件商城"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -1,36 +0,0 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '商城',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view
|
||||
class="bg-white overflow-hidden pt-2 px-4"
|
||||
:style="{ marginTop: safeAreaInsets?.top + 'px' }"
|
||||
>
|
||||
<view class="text-center text-3xl mt-8">
|
||||
鸽友们好,我是
|
||||
<text class="text-red-500">菲鸽</text>
|
||||
</view>
|
||||
<RequestComp />
|
||||
<UploadComp />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import RequestComp from './components/request.vue'
|
||||
import UploadComp from './components/upload.vue'
|
||||
|
||||
// 获取屏幕边界到安全区域距离
|
||||
const { safeAreaInsets } = uni.getSystemInfoSync()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.test-css {
|
||||
// mt-4=>1rem=>16px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
@ -1,56 +0,0 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'demo',
|
||||
style: {
|
||||
navigationBarTitleText: '请求',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="p-6 text-center">
|
||||
<view class="my-2">使用的是 laf 云后台</view>
|
||||
<view class="text-green-400">我的推荐码,可以获得佣金</view>
|
||||
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="my-2">
|
||||
<a class="my-2" :href="recommendUrl" target="_blank">{{ recommendUrl }}</a>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef H5 -->
|
||||
<view class="my-2 text-left text-sm">{{ recommendUrl }}</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- http://localhost:9000/#/pages/index/request -->
|
||||
<wd-button @click="run" class="my-6">发送请求</wd-button>
|
||||
<view class="h-12">
|
||||
<view v-if="loading">loading...</view>
|
||||
<block v-else>
|
||||
<view class="text-xl">请求数据如下</view>
|
||||
<view class="text-green leading-8">{{ JSON.stringify(data) }}</view>
|
||||
</block>
|
||||
</view>
|
||||
<wd-button type="error" @click="reset" class="my-6" :disabled="!data">重置数据</wd-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
|
||||
|
||||
const recommendUrl = ref('http://laf.run/signup?code=ohaOgIX')
|
||||
|
||||
// const initialData = {
|
||||
// name: 'initialData',
|
||||
// id: '1234',
|
||||
// }
|
||||
const initialData = undefined
|
||||
// 适合少部分全局性的接口————多个页面都需要的请求接口,额外编写一个 Service 层
|
||||
const { loading, error, data, run } = useRequest<IFooItem>(() => getFooAPI('菲鸽'), {
|
||||
immediate: true,
|
||||
initialData,
|
||||
})
|
||||
const reset = () => {
|
||||
data.value = initialData
|
||||
}
|
||||
</script>
|
@ -1,30 +0,0 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationBarTitleText: '上传-状态一体化',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="p-4 text-center">
|
||||
<wd-button @click="run">选择图片并上传</wd-button>
|
||||
<view v-if="loading" class="text-blue h-10">上传...</view>
|
||||
<template v-else>
|
||||
<view class="m-2">上传后返回的接口数据:</view>
|
||||
<view class="m-2">{{ data }}</view>
|
||||
<view class="h-80 w-full">
|
||||
<image v-if="data" :src="data || data" mode="scaleToFill" />
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const { loading, data, run } = useUpload({ user: '菲鸽' })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
//
|
||||
</style>
|
@ -9,37 +9,18 @@
|
||||
|
||||
<template>
|
||||
<view class="home-root">
|
||||
<view class="container">
|
||||
<!-- 左侧圆形部分 -->
|
||||
<view class="circle">宇森科技</view>
|
||||
|
||||
<!-- 右侧矩形部分 -->
|
||||
<view class="rectangle">
|
||||
<text>成立历史,介绍来历,参与事情。</text>
|
||||
</view>
|
||||
</view>
|
||||
<image class="w-full" src="/static/index/index_bg.jpg" mode="widthFix" />
|
||||
<view class="container"></view>
|
||||
</view>
|
||||
<Tabbar />
|
||||
</template>
|
||||
|
||||
<script lang="js" setup>
|
||||
// TODO
|
||||
import Tabbar from '@/components/tabbar.vue'
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.home-root {
|
||||
@apply bg-white min-h-screen flex items-center justify-center;
|
||||
}
|
||||
|
||||
.container {
|
||||
@apply flex items-center p-4;
|
||||
}
|
||||
|
||||
.circle {
|
||||
@apply w-20 h-20 rounded-full flex items-center justify-center text-center bg-blue-200 text-black;
|
||||
}
|
||||
|
||||
.rectangle {
|
||||
@apply w-60 h-20 ml-4 flex items-center justify-center text-black border rounded-lg;
|
||||
border-color: #000000;
|
||||
page {
|
||||
background-color: #0f71f6;
|
||||
}
|
||||
</style>
|
||||
|
89
src/pages/product/index.vue
Normal file
89
src/pages/product/index.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationBarTitleText: '商品详情',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="p-1 bg-white">
|
||||
<!-- 轮播图:多张图片 -->
|
||||
<view v-if="product.product_images && product.product_images.length > 0" class="swiper-container mb-4">
|
||||
<swiper autoplay="true" interval="3000" class="rounded-lg">
|
||||
<swiper-item @click="previewImage(index)" v-for="(image, index) in product.product_images" :key="index">
|
||||
<image :src="getStrapiImage(image)" mode="aspectFit" class="w-full h-48 rounded-lg" alt="Product Image" />
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
|
||||
<!-- 商品名称 -->
|
||||
<view class="text-xl font-bold mb-2">{{ product.name }}</view>
|
||||
|
||||
<!-- 商品描述 -->
|
||||
<view class="text-sm text-gray-600 mb-4">{{ product.description }}</view>
|
||||
|
||||
<!-- 商品分类 -->
|
||||
<view v-if="product.categoryType" class="text-sm text-gray-500 mb-4">
|
||||
分类: {{ product.categoryType.map(item => item.categoryName) }}
|
||||
</view>
|
||||
|
||||
<!-- 商品标签 -->
|
||||
<view class="flex gap-1">
|
||||
<wd-tag v-for="tag in product.tags" :bg-color="tag.color" mark>{{ tag.tag }}</wd-tag>
|
||||
</view>
|
||||
|
||||
<view class="pt-1" v-html="product.detail"></view>
|
||||
|
||||
<!-- 购买按钮 -->
|
||||
<button class="w-full py-3 bg-blue-500 text-white text-center rounded-lg pos-fixed bottom-0">
|
||||
联系客服
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { httpGet } from '@/utils/http'
|
||||
import { getStrapiImage } from '@/utils/image'
|
||||
|
||||
// 模拟从 Strapi 获取数据的方法
|
||||
const product = ref({})
|
||||
|
||||
|
||||
// 预览图片
|
||||
function previewImage(currentIndex) {
|
||||
const imageUrls = product.value.product_images.map(image => getStrapiImage(image));
|
||||
|
||||
uni.previewImage({
|
||||
urls: imageUrls, // 传入所有图片的数组
|
||||
current: imageUrls[currentIndex], // 当前点击的图片
|
||||
});
|
||||
}
|
||||
|
||||
// 模拟获取商品详情的方法
|
||||
const fetchProduct = async (id) => {
|
||||
// 替换为实际的 API 调用
|
||||
const res = await httpGet(`/products/${id}?populate=*`)
|
||||
product.value = res.data
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.id) {
|
||||
fetchProduct(options.id)
|
||||
} else {
|
||||
uni.showToast({ icon: 'none', title: '该商品已下架' })
|
||||
uni.navigateTo({ url: "/pages/shop/index" })
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-container {
|
||||
height: 12rem;
|
||||
}
|
||||
|
||||
page {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
</style>
|
107
src/pages/search/index.vue
Normal file
107
src/pages/search/index.vue
Normal file
@ -0,0 +1,107 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationBarTitleText: '搜索页面',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<!-- 展示搜索条例 -->
|
||||
<wd-search class="pos-fixed top-40px w-full z-999" v-model="searchValue" cancel-txt="搜索" @search="search"
|
||||
@cancel="cancel" />
|
||||
<!-- 历史开发的软件 -->
|
||||
<view class="flex flex-col gap-2 items-center pt-1 mt-50px pb-16">
|
||||
<view v-for="product in products" :key="product.id" @click="goProduct(product)"
|
||||
class="w-95vw pt-2 shadow-sm rounded-2 bg-white flex flex-col">
|
||||
<image :src="getStrapiImage(product.product_image)" mode="heightFix" alt="Card Image"
|
||||
class="w-full h-48 rounded-t-lg flex-auto m-auto" />
|
||||
<view class="p-4">
|
||||
<h2 class="text-xl font-bold mb-2 flex items-center gap-1">
|
||||
{{ product.name }}
|
||||
<wd-tag v-if="product.tags && product.tags.length" :bg-color="product.tags[0].color" mark>
|
||||
{{ product.tags[0].tag }}
|
||||
</wd-tag>
|
||||
</h2>
|
||||
<p class="text-gray-700 mb-4">{{ product.description }}</p>
|
||||
<view class="flex gap-1">
|
||||
<wd-tag v-for="tag in product.tags" :key="tag.id" :bg-color="tag.color" mark>{{ tag.tag }}</wd-tag>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { httpGet } from '@/utils/http';
|
||||
import { getStrapiImage } from '@/utils/image';
|
||||
|
||||
const products = ref([]);
|
||||
const searchValue = ref('');
|
||||
const categoryId = ref(null);
|
||||
|
||||
function goProduct(p) {
|
||||
uni.navigateTo({ url: `/pages/product/index?id=${p.documentId}` });
|
||||
}
|
||||
|
||||
function search() {
|
||||
if (categoryId.value) {
|
||||
fetchProductsByCategory(categoryId.value);
|
||||
} else {
|
||||
loadSearchData(searchValue.value);
|
||||
}
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
if (categoryId.value) {
|
||||
fetchProductsByCategory(categoryId.value);
|
||||
} else {
|
||||
loadSearchData(searchValue.value);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSearchData(keyword) {
|
||||
try {
|
||||
const res = await httpGet(
|
||||
`/products?populate=*&filters[$or][0][name][$contains]=${keyword}&filters[$or][1][description][$contains]=${keyword}`
|
||||
);
|
||||
products.value = res.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchProductsByCategory = async (categoryId) => {
|
||||
try {
|
||||
let query = ''
|
||||
if (searchValue.value && searchValue.value != '') {
|
||||
query = `&filters[$or][0][name][$contains]=${searchValue.value}&filters[$or][1][description][$contains]=${searchValue.value}`
|
||||
}
|
||||
const res = await httpGet(
|
||||
`/products?populate=*&filters[categoryType][id][$in]=${categoryId}${query}`
|
||||
);
|
||||
products.value = res.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.keyword) {
|
||||
searchValue.value = options.keyword;
|
||||
loadSearchData(searchValue.value);
|
||||
} else if (options.categoryId) {
|
||||
categoryId.value = options.categoryId;
|
||||
fetchProductsByCategory(categoryId.value);
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
</style>
|
188
src/pages/shop/index.vue
Normal file
188
src/pages/shop/index.vue
Normal file
@ -0,0 +1,188 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationBarTitleText: '宇森科技软件商城',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<wd-search v-model="value" @search="search" @cancel="cancel" cancel-txt="搜索" />
|
||||
|
||||
<!-- 这里是推广图片 -->
|
||||
<view class="p-2">
|
||||
<wd-swiper :list="swiperList" autoplay :current="current" @click="handleClick" @change="onChange"></wd-swiper>
|
||||
</view>
|
||||
|
||||
<!-- 下面是分类商品 -->
|
||||
<view class="rounded-4 p-2">
|
||||
<wd-grid :column="3">
|
||||
<wd-grid-item @click="goCategory(item)" icon-size="30px" use-icon-slot v-for="item in categorys"
|
||||
:text="item.categoryName">
|
||||
<template #icon>
|
||||
<image class="w-30px" mode="widthFix" :src="getStrapiImage(item.icon)" />
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
</wd-grid>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<!-- 推荐列表 -->
|
||||
<view class="pos-relative flex gap-2 items-center overflow-hidden mt-2 pl-2">
|
||||
<view class="flex transition-all gap-2" :style="{ transform: `translateX(${translateX}px)` }"
|
||||
@touchstart="startDrag" @touchmove="drag" @touchend="endDrag">
|
||||
<!-- 卡片1 -->
|
||||
<view v-for="product in products.slice(0, 4)"
|
||||
class="min-w-81vw w-81vw shadow-2xl bg-white shadow-lg rounded-lg max-w-sm p-4 flex flex-col">
|
||||
<image :src="getStrapiImage(product.product_image)" mode="heightFix" alt="Card Image"
|
||||
class="h-48 rounded-t-lg flex-auto m-auto" />
|
||||
<view class="p-4">
|
||||
<view @click="goProduct(product)" class="text-xl font-bold mb-2">{{ product.name }}</view>
|
||||
<view class="text-gray-700 mb-4" v-html="product.description">
|
||||
</view>
|
||||
<button class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 transition">
|
||||
联系我们
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 历史开发的软件 -->
|
||||
<view class="flex flex-col gap-1 items-center pt-1 mt-1 pb-16">
|
||||
<view @click="goProduct(product)" v-for="product in products.slice(4)"
|
||||
class="w-95vw pt-2 shadow-sm rounded-2 bg-white flex flex-col">
|
||||
<image :src="getStrapiImage(product.product_image)" mode="heightFix" alt="Card Image"
|
||||
class="w-full h-48 rounded-t-lg flex-auto m-auto" />
|
||||
<view class="p-4">
|
||||
<h2 class="text-xl font-bold mb-2 flex items-center gap-1">
|
||||
{{ product.name }}
|
||||
<wd-tag v-if="product.tags && product.tags.length" :bg-color="product.tags[0].color" mark>{{
|
||||
product.tags[0].tag
|
||||
}}</wd-tag>
|
||||
</h2>
|
||||
<p class="text-gray-700 mb-4">{{ product.description }}</p>
|
||||
<view class="flex gap-1">
|
||||
<wd-tag v-for="tag in product.tags" :bg-color="tag.color" mark>{{ tag.tag }}</wd-tag>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<Tabbar />
|
||||
</template>
|
||||
|
||||
<script lang="js" setup>
|
||||
import Tabbar from '@/components/tabbar.vue'
|
||||
import { httpGet } from '@/utils/http'
|
||||
import { getStrapiImage } from '@/utils/image'
|
||||
|
||||
const value = ref('')
|
||||
const current = ref(0)
|
||||
const recommends = ref([])
|
||||
const swiperList = ref([])
|
||||
const categorys = ref([])
|
||||
const products = ref([])
|
||||
|
||||
function goCategory(c) {
|
||||
uni.navigateTo({ url: `/pages/search/index?categoryId=${c.id}` });
|
||||
}
|
||||
|
||||
function goProduct(p) {
|
||||
uni.navigateTo({ url: `/pages/product/index?id=${p.documentId}` })
|
||||
}
|
||||
|
||||
// 获取推荐信息
|
||||
async function getRecommends() {
|
||||
const res = await httpGet('/recommends?populate=*')
|
||||
recommends.value = res.data
|
||||
recommends.value.forEach((item) => {
|
||||
item.url = getStrapiImage(item.image)
|
||||
console.log(item.url)
|
||||
swiperList.value.push(item.url)
|
||||
})
|
||||
}
|
||||
|
||||
function search() {
|
||||
uni.navigateTo({ url: '/pages/search/index?keyword=' + value.value })
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
search()
|
||||
}
|
||||
|
||||
// 获取分类
|
||||
async function getCategorys() {
|
||||
const res = await httpGet('/categorys?populate=*')
|
||||
categorys.value = res.data
|
||||
}
|
||||
|
||||
// 获取商品信息
|
||||
async function getProducts() {
|
||||
const res = await httpGet('/products?populate=*')
|
||||
products.value = res.data
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
getRecommends()
|
||||
getCategorys()
|
||||
getProducts()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
|
||||
function handleClick(e) {
|
||||
console.log(e)
|
||||
}
|
||||
function onChange(e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
// 控制卡片平移的X轴距离
|
||||
const translateX = ref(0)
|
||||
|
||||
// 当前卡片的索引
|
||||
const currentCardIndex = ref(1)
|
||||
|
||||
// 记录开始触摸时的X轴位置
|
||||
const startX = ref(0)
|
||||
|
||||
// 开始拖动时触发的事件
|
||||
const startDrag = (e) => {
|
||||
startX.value = e.touches[0].clientX
|
||||
}
|
||||
|
||||
// 拖动中时触发的事件
|
||||
const drag = (e) => {
|
||||
const deltaX = e.touches[0].clientX - startX.value
|
||||
translateX.value = deltaX - currentCardIndex.value * ((81 * window.innerWidth) / 100)
|
||||
}
|
||||
|
||||
// 结束拖动时触发的事件
|
||||
const endDrag = (e) => {
|
||||
const deltaX = e.changedTouches[0].clientX - startX.value
|
||||
const threshold = 50 // 滑动的最小距离,超过这个距离才会切换卡片
|
||||
|
||||
// 向右滑动
|
||||
if (deltaX > threshold && currentCardIndex.value > 0) {
|
||||
currentCardIndex.value--
|
||||
}
|
||||
// 向左滑动
|
||||
else if (deltaX < -threshold && currentCardIndex.value < 2) {
|
||||
currentCardIndex.value++
|
||||
}
|
||||
|
||||
// 根据新的卡片索引调整 translateX
|
||||
translateX.value = -currentCardIndex.value * ((81 * window.innerWidth) / 100)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
</style>
|
BIN
src/static/index/index_bg.jpg
Normal file
BIN
src/static/index/index_bg.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 358 KiB |
18
src/store/routers.js
Normal file
18
src/store/routers.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const initState = { path: '/pages/index/index', }
|
||||
|
||||
export const useRouterStore = defineStore(
|
||||
'routers',
|
||||
() => {
|
||||
const routers = ref({ ...initState })
|
||||
|
||||
return {
|
||||
routers
|
||||
}
|
||||
},
|
||||
{
|
||||
persist: true,
|
||||
},
|
||||
)
|
@ -1,7 +1,10 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const initState = { nickname: '', avatar: '' }
|
||||
const initState = {
|
||||
token:
|
||||
'c9f6de432ba6edb6c56d0a8d8e0feaaa8bfcf8b8d82ecf9976fd1fc2567b6f8c8f3775cfab90dd12e0124c486ed18bbd8c6ed509ee492c659c2b3b8c6bd102acc67b179095cdbc6cc1ccf79c0310f1a3be0771d29811ab88297a441107deabb493654c3297d39d60719340a4a4b82e692a99decbefd2c430d9a4c2561c0103f3',
|
||||
}
|
||||
|
||||
export const useUserStore = defineStore(
|
||||
'user',
|
||||
|
6
src/types/uni-pages.d.ts
vendored
6
src/types/uni-pages.d.ts
vendored
@ -5,12 +5,14 @@
|
||||
|
||||
interface NavigateToOptions {
|
||||
url: "/pages/index/index" |
|
||||
"/pages/about/about";
|
||||
"/pages/product/index" |
|
||||
"/pages/search/index" |
|
||||
"/pages/shop/index";
|
||||
}
|
||||
interface RedirectToOptions extends NavigateToOptions {}
|
||||
|
||||
interface SwitchTabOptions {
|
||||
url: "/pages/index/index" | "/pages/about/about"
|
||||
url: "/pages/index/index" | "/pages/shop/index"
|
||||
}
|
||||
|
||||
type ReLaunchOptions = NavigateToOptions | SwitchTabOptions;
|
||||
|
28
src/utils/image.ts
Normal file
28
src/utils/image.ts
Normal file
@ -0,0 +1,28 @@
|
||||
const baseUrl = import.meta.env.VITE_STATIC_BASEURL
|
||||
|
||||
// 获取 Strapi 中图片的工具函数// 获取 Strapi 中图片的工具函数
|
||||
export function getStrapiImage(imageData) {
|
||||
try {
|
||||
// 判断imageData 如果是对象且不为数组就直接返回url路径
|
||||
if (typeof imageData === 'object' && !Array.isArray(imageData)) {
|
||||
return baseUrl + imageData.url
|
||||
}
|
||||
|
||||
// 确保返回的数据中包含图片信息
|
||||
if (imageData && Array.isArray(imageData)) {
|
||||
if (imageData.length === 1) {
|
||||
console.log('imageData:', baseUrl + imageData[0].url)
|
||||
// 如果只有一个图片,返回单个 URL
|
||||
return baseUrl + imageData[0].url
|
||||
} else {
|
||||
// 如果有多个图片,返回 URL 数组
|
||||
return imageData.map((image) => baseUrl + image.url)
|
||||
}
|
||||
} else {
|
||||
throw new Error('没有找到图片数据')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解析图片数据失败:', error)
|
||||
return null
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user