Prechádzať zdrojové kódy

Merge branch 'release/release-202205061030'

tangning 3 rokov pred
rodič
commit
b527ffe574
100 zmenil súbory, kde vykonal 8837 pridanie a 49267 odobranie
  1. 5 2
      .env.development
  2. 3 1
      .env.production
  3. 37 0
      .env.uat
  4. 3 2
      .eslintrc.js
  5. 2 1
      .husky/lintstagedrc.js
  6. 0 21
      build/vite/optimizer.ts
  7. 0 25
      build/vite/plugin/hmr.ts
  8. 5 6
      build/vite/plugin/index.ts
  9. 5 4
      build/vite/plugin/styleImport.ts
  10. 1 0
      build/vite/proxy.ts
  11. 2 0
      docker/.env
  12. 42 0
      docker/conf.d/default.conf
  13. 31 0
      docker/docker-compose.yml
  14. 3 0
      docker/env.example
  15. 43 0
      docker/nginx.conf
  16. 100 0
      docker/setting/general.conf
  17. 117 0
      docker/setting/general_production.conf
  18. 112 0
      docker/setting/general_staging.conf
  19. 8 0
      docker/setting/proxy.conf
  20. 32 0
      docker/setting/security.conf
  21. 48 0
      docker/start.sh
  22. 2 2
      mock/_util.ts
  23. 39 0
      mock/advertisement/selectAll.ts
  24. 39 0
      mock/advertisement/selectId.ts
  25. 1 1
      mock/company/selectCompanyByType.ts
  26. 2 2
      mock/company/selectCompanyNum.ts
  27. 2 2
      mock/demo/account.ts
  28. 202 0
      mock/demo/system.ts
  29. 81 0
      mock/devices/pageList.ts
  30. 43 0
      mock/feedback/list.ts
  31. 85 0
      mock/house/selectHouseByType.ts
  32. 50 0
      mock/member/list.ts
  33. 71 0
      mock/order/list.ts
  34. 73 0
      mock/product/category.ts
  35. 51 0
      mock/product/list.ts
  36. 38 0
      mock/scene/list.ts
  37. 44 0
      mock/scene/live.ts
  38. 43 0
      mock/staff/list.ts
  39. 38 2
      mock/sys/user.ts
  40. 0 41054
      package-lock.json
  41. 98 67
      package.json
  42. 5053 7891
      pnpm-lock.yaml
  43. BIN
      public/resource/img/logo.png
  44. BIN
      public/resource/img/logo1 (2).png
  45. BIN
      public/resource/img/pic_bg@2x.png
  46. 1 0
      src/App.vue
  47. 16 0
      src/api/account/index.ts
  48. 7 0
      src/api/account/model.ts
  49. 112 0
      src/api/advertisement/list.ts
  50. 42 0
      src/api/advertisement/model.ts
  51. 20 0
      src/api/bulletin/model.ts
  52. 63 0
      src/api/bulletin/rent.ts
  53. 111 3
      src/api/corporation/list.ts
  54. 104 0
      src/api/corporation/modal.ts
  55. 100 0
      src/api/corporation/model.ts
  56. 64 0
      src/api/device/list.ts
  57. 70 0
      src/api/device/model.ts
  58. 0 0
      src/api/error/index.ts
  59. 20 0
      src/api/feedback/list.ts
  60. 20 0
      src/api/feedback/model.ts
  61. 20 0
      src/api/member/list.ts
  62. 19 0
      src/api/member/model.ts
  63. 1 22
      src/api/model/baseModel.ts
  64. 90 0
      src/api/order/list.ts
  65. 30 0
      src/api/order/model.ts
  66. 111 0
      src/api/product/category.ts
  67. 93 0
      src/api/product/list.ts
  68. 43 0
      src/api/product/model.ts
  69. 81 0
      src/api/scene/list.ts
  70. 165 0
      src/api/scene/live.ts
  71. 95 0
      src/api/scene/model.ts
  72. 105 0
      src/api/staff/list.ts
  73. 30 0
      src/api/staff/model.ts
  74. 2 2
      src/api/sys/menu.ts
  75. 51 17
      src/api/sys/model/userModel.ts
  76. 39 7
      src/api/sys/user.ts
  77. 12 0
      src/api/system/error.ts
  78. 7 0
      src/api/system/model/accountModel.ts
  79. 12 0
      src/api/system/model/areaModel.ts
  80. 15 0
      src/api/system/model/optionsModel.ts
  81. 100 0
      src/api/system/model/systemModel.ts
  82. 111 0
      src/api/system/system.ts
  83. BIN
      src/assets/images/header.jpg
  84. BIN
      src/assets/images/logo.png
  85. 81 86
      src/components/CardList/src/CardList.vue
  86. 1 1
      src/components/CardList/src/data.ts
  87. 2 2
      src/components/CodeEditor/src/codemirror/codemirror.css
  88. 1 1
      src/components/Container/src/collapse/CollapseContainer.vue
  89. 9 9
      src/components/ContextMenu/src/ContextMenu.vue
  90. 37 4
      src/components/Cropper/src/CopperModal.vue
  91. 2 0
      src/components/Cropper/src/Cropper.vue
  92. 16 4
      src/components/Cropper/src/CropperAvatar.vue
  93. 1 1
      src/components/Drawer/src/BasicDrawer.vue
  94. 1 2
      src/components/Drawer/src/typing.ts
  95. 17 5
      src/components/Form/src/BasicForm.vue
  96. 22 10
      src/components/Form/src/components/ApiSelect.vue
  97. 2 0
      src/components/Form/src/helper.ts
  98. 7 7
      src/components/Form/src/hooks/useFormEvents.ts
  99. 2 1
      src/components/Form/src/hooks/useFormValues.ts
  100. 0 0
      src/components/Form/src/hooks/useLabelWidth.ts

+ 5 - 2
.env.development

@@ -6,14 +6,17 @@ VITE_PUBLIC_PATH = /
 
 # Cross-domain proxy, you can configure multiple
 # Please note that no line breaks
-VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]]
+# http://192.168.0.38:8190/shop
+VITE_PROXY = [["/basic-api","https://cszfb.4dkankan.com/basic-api"],["/upload","http://localhost:3300/upload"],["/zfb-api","https://cszfb.4dkankan.com"]]
+# VITE_PROXY = [["/basic-api","http://192.168.0.47:8190"],["/upload","http://localhost:3300/upload"],["/zfb-api","http://192.168.0.47:7081"]]
+#["/zfb-api","http://192.168.0.47:7081"]]
 # VITE_PROXY=[["/api","https://vvbin.cn/test"]]
 
 # Delete console
 VITE_DROP_CONSOLE = false
 
 # Basic interface address SPA
-VITE_GLOB_API_URL=/basic-api
+VITE_GLOB_API_URL=
 
 # File upload address, optional
 VITE_GLOB_UPLOAD_URL=/upload

+ 3 - 1
.env.production

@@ -7,6 +7,7 @@ VITE_PUBLIC_PATH = /
 # Delete console
 VITE_DROP_CONSOLE = true
 
+VITE_PROXY = [["/basic-api","https://cszfb.4dkankan.com/basic-api"],["/upload","http://localhost:3300/upload"],["/zfb-api","https://cszfb.4dkankan.com"]]
 # Whether to enable gzip or brotli compression
 # Optional: gzip | brotli | none
 # If you need multiple forms, you can use `,` to separate
@@ -16,7 +17,8 @@ VITE_BUILD_COMPRESS = 'none'
 VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
 
 # Basic interface address SPA
-VITE_GLOB_API_URL=/basic-api
+# VITE_GLOB_API_URL=/basic-api
+VITE_GLOB_API_URL=
 
 # File upload address, optional
 # It can be forwarded by nginx or write the actual address directly

+ 37 - 0
.env.uat

@@ -0,0 +1,37 @@
+# Whether to open mock
+VITE_USE_MOCK = true
+
+# public path
+VITE_PUBLIC_PATH = /
+
+# Delete console
+VITE_DROP_CONSOLE = true
+
+VITE_PROXY = [["/basic-api","https://cszfb.4dkankan.com/basic-api"],["/upload","http://localhost:3300/upload"],["/zfb-api","https://cszfb.4dkankan.com"]]
+# Whether to enable gzip or brotli compression
+# Optional: gzip | brotli | none
+# If you need multiple forms, you can use `,` to separate
+VITE_BUILD_COMPRESS = 'none'
+
+# Whether to delete origin files when using compress, default false
+VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
+
+# Basic interface address SPA
+# VITE_GLOB_API_URL=/basic-api
+VITE_GLOB_API_URL=
+
+# File upload address, optional
+# It can be forwarded by nginx or write the actual address directly
+VITE_GLOB_UPLOAD_URL=/upload
+
+# Interface prefix
+VITE_GLOB_API_URL_PREFIX=
+
+# Whether to enable image compression
+VITE_USE_IMAGEMIN= true
+
+# use pwa
+VITE_USE_PWA = false
+
+# Is it compatible with older browsers
+VITE_LEGACY = false

+ 3 - 2
.eslintrc.js

@@ -55,8 +55,6 @@ module.exports = defineConfig({
     'space-before-function-paren': 'off',
 
     'vue/attributes-order': 'off',
-    'vue/v-on-event-hyphenation': 'off',
-    'vue/multi-word-component-names': 'off',
     'vue/one-component-per-file': 'off',
     'vue/html-closing-bracket-newline': 'off',
     'vue/max-attributes-per-line': 'off',
@@ -64,6 +62,8 @@ module.exports = defineConfig({
     'vue/singleline-html-element-content-newline': 'off',
     'vue/attribute-hyphenation': 'off',
     'vue/require-default-prop': 'off',
+    'vue/require-explicit-emits': 'off',
+    'vue/no-useless-template-attributes': 'off',
     'vue/html-self-closing': [
       'error',
       {
@@ -76,5 +76,6 @@ module.exports = defineConfig({
         math: 'always',
       },
     ],
+    'vue/multi-word-component-names': 'off',
   },
 });

+ 2 - 1
.husky/lintstagedrc.js

@@ -2,7 +2,8 @@ module.exports = {
   '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
   '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
   'package.json': ['prettier --write'],
-  '*.vue': ['eslint --fix', 'prettier --write', 'stylelint --fix'],
+  '*.vue': ['eslint --fix', 'prettier --write'],
   '*.{scss,less,styl,html}': ['stylelint --fix', 'prettier --write'],
   '*.md': ['prettier --write'],
 };
+// '*.vue': ['eslint --fix', 'prettier --write', 'stylelint --fix'],

+ 0 - 21
build/vite/optimizer.ts

@@ -1,21 +0,0 @@
-// TODO
-import type { GetManualChunk } from 'rollup';
-
-//
-const vendorLibs: { match: string[]; output: string }[] = [
-  // {
-  //   match: ['xlsx'],
-  //   output: 'xlsx',
-  // },
-];
-
-// @ts-ignore
-export const configManualChunk: GetManualChunk = (id: string) => {
-  if (/[\\/]node_modules[\\/]/.test(id)) {
-    const matchItem = vendorLibs.find((item) => {
-      const reg = new RegExp(`[\\/]node_modules[\\/]_?(${item.match.join('|')})(.*)`, 'ig');
-      return reg.test(id);
-    });
-    return matchItem ? matchItem.output : null;
-  }
-};

+ 0 - 25
build/vite/plugin/hmr.ts

@@ -1,25 +0,0 @@
-import type { Plugin } from 'vite';
-
-/**
- * TODO
- * Temporarily solve the Vite circular dependency problem, and wait for a better solution to fix it later. I don't know what problems this writing will bring.
- * @returns
- */
-
-export function configHmrPlugin(): Plugin {
-  return {
-    name: 'singleHMR',
-    handleHotUpdate({ modules, file }) {
-      if (file.match(/xml$/)) return [];
-
-      modules.forEach((m) => {
-        if (!m.url.match(/\.(css|less)/)) {
-          m.importedModules = new Set();
-          m.importers = new Set();
-        }
-      });
-
-      return modules;
-    },
-  };
-}

+ 5 - 6
build/vite/plugin/index.ts

@@ -14,7 +14,7 @@ import { configVisualizerConfig } from './visualizer';
 import { configThemePlugin } from './theme';
 import { configImageminPlugin } from './imagemin';
 import { configSvgIconsPlugin } from './svgSprite';
-import { configHmrPlugin } from './hmr';
+import pluginRewriteAll from 'vite-plugin-rewrite-all';
 
 export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
   const {
@@ -37,9 +37,6 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
   // vite-plugin-windicss
   vitePlugins.push(windiCSS());
 
-  // TODO
-  !isBuild && vitePlugins.push(configHmrPlugin());
-
   // @vitejs/plugin-legacy
   VITE_LEGACY && isBuild && vitePlugins.push(legacy());
 
@@ -61,12 +58,14 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
   // rollup-plugin-visualizer
   vitePlugins.push(configVisualizerConfig());
 
-  //vite-plugin-theme
+  // vite-plugin-theme
   vitePlugins.push(configThemePlugin(isBuild));
 
+  vitePlugins.push(pluginRewriteAll());
+
   // The following plugins only work in the production environment
   if (isBuild) {
-    //vite-plugin-imagemin
+    // vite-plugin-imagemin
     VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
 
     // rollup-plugin-gzip

+ 5 - 4
build/vite/plugin/styleImport.ts

@@ -4,10 +4,10 @@
  */
 import styleImport from 'vite-plugin-style-import';
 
-export function configStyleImportPlugin(isBuild: boolean) {
-  if (!isBuild) {
-    return [];
-  }
+export function configStyleImportPlugin(_isBuild: boolean) {
+  // if (!isBuild) {
+  //   return [];
+  // }
   const styleImportPlugin = styleImport({
     libs: [
       {
@@ -19,6 +19,7 @@ export function configStyleImportPlugin(isBuild: boolean) {
             'anchor-link',
             'sub-menu',
             'menu-item',
+            'menu-divider',
             'menu-item-group',
             'breadcrumb-item',
             'breadcrumb-separator',

+ 1 - 0
build/vite/proxy.ts

@@ -21,6 +21,7 @@ export function createProxy(list: ProxyList = []) {
     const isHttps = httpsRE.test(target);
 
     // https://github.com/http-party/node-http-proxy#options
+    console.log('prefix', prefix);
     ret[prefix] = {
       target: target,
       changeOrigin: true,

+ 2 - 0
docker/.env

@@ -0,0 +1,2 @@
+SXZ_HTTP_PORT=7776
+CONTAINER_NAME=sxz_web

+ 42 - 0
docker/conf.d/default.conf

@@ -0,0 +1,42 @@
+server {
+  listen 80 ;
+  # root /opt/dist;
+  root /opt/dist;
+  index index.html index.htm index.nginx-debian.html;
+  # MIME
+  include /etc/nginx/mime.types;
+  default_type application/octet-stream;
+  # Display nginx Version number in error or http header may result in hacker to search for known vulnerability. Therefore, the version number should be removed for every http response.
+  server_tokens "off";
+  #charset utf-8;
+  # This directive, by default, is disabled to allow small packets to wait for a specified period before they are sent at once. To allow all data to be sent at once, this directive is enabled.
+  tcp_nodelay on;
+  #  Because we have enabled tcp_nodelay directive, small packets are sent at once. However, if you still want to make use of John Nagle’s buffering algorithm, we can also enable the tcp_nopush to add packets to each other and send them all at once.
+  tcp_nopush on;
+  # Defines a timeout for reading client request body. The timeout is set only for a period between two successive read operations, not for the transmission of the whole request body. If a client does not transmit anything within this time, the 408 (Request Time-out) error is returned to the client.
+  client_body_timeout 12;
+  # Defines a timeout for reading client request header. If a client does not transmit the entire header within this time, the 408 (Request Time-out) error is returned to the client.
+  client_header_timeout 12;
+  # This directive sets the buffer size for the request body. If you plan to run the webserver on 64-bit systems, you need to set the value to 16k. If you want to run the webserver on the 32-bit system, set the value to 8k.
+  client_body_buffer_size 1M;
+  # Similar to the previous directive, only instead it handles the client header size. For all intents and purposes, 1K is usually a decent size for this directive not unless you're sending mayopic stuff via header i.e permissions.
+  client_header_buffer_size 1k;
+  # The maximum number and size of buffers for large client headers.
+  large_client_header_buffers 2 1k;
+  # The maximum allowed size for a client request. If the maximum size is exceeded, then Nginx will spit out a 413 error or Request Entity Too Large.
+  client_max_body_size 500M;
+  # Defines the maximum size of an entry in the MIME types hash tables.
+  types_hash_max_size 4096;
+  # The first parameter sets a timeout during which a keep-alive client connection will stay open on the server side. The zero value disables keep-alive client connections. The optional second parameter sets a value in the “Keep-Alive: timeout=time” response header field. Two parameters may differ. The “Keep-Alive: timeout=time” header field is recognized by Mozilla and Konqueror. The default is 75 seconds.
+  keepalive_timeout 120s;
+  # Configure a number of requests to keep alive for a specific period of time.  You can set the number of requests to 20 or 30.
+  keepalive_requests 120;
+  # if you want to disable keepalive connection for a specific group of browsers, use this directive.
+  #keepalive_disable;
+  #Sets a timeout for transmitting a response to the client. The timeout is set only between two successive write operations, not for the transmission of the whole response. If the client does not receive anything within this time, the connection is closed.
+  send_timeout 75s;
+
+  include /etc/nginx/setting/general.conf;
+  include /etc/nginx/setting/security.conf;
+  include /etc/nginx/setting/proxy.conf;
+}

+ 31 - 0
docker/docker-compose.yml

@@ -0,0 +1,31 @@
+version: "3.7"
+
+# docker network create nginx_bridge
+# networks:
+#   nginx_bridge:
+#     driver: bridge
+
+services:
+  nginx:
+    image: nginx:stable-alpine
+    # build:
+    #   context: .
+    #   dockerfile: Dockerfile
+    container_name: $CONTAINER_NAME
+    restart: always
+    privileged: true
+    environment:
+      - TZ=Asia/Shanghai
+    ports:
+      - $SXZ_HTTP_PORT:80
+      # - 80:80
+      # - 443:443
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ./nginx.conf:/etc/nginx/nginx.conf:ro
+      - ./conf.d:/etc/nginx/conf.d
+      - ./setting:/etc/nginx/setting
+      - /var/log/$CONTAINER_NAME/logs:/var/log/nginx
+      - ./dist:/opt/dist:ro
+    # networks:
+    #   - nginx_bridge

+ 3 - 0
docker/env.example

@@ -0,0 +1,3 @@
+SXZ_HTTP_PORT=6060
+CONTAINER_NAME=sxz_model_admin
+#SXZ_HTTPS_PORT=6060

+ 43 - 0
docker/nginx.conf

@@ -0,0 +1,43 @@
+# user  nginx;
+worker_processes auto;
+
+error_log /var/log/nginx/error.log warn;
+pid /var/run/nginx.pid;
+
+events {
+    # The maximum number of connections that each worker process can handle simultaneously. The default is 512, but most systems have enough resources to support a larger number. The appropriate setting depends on the size of the server and the nature of the traffic, and can be discovered through testing.
+    worker_connections 65535;
+    # This directive allows a worker to accept many connections in the queue at a time. A queue in this context simply means a sequence of data objects waiting to be processed.
+    multi_accept on;
+    # With this directive worker processes will accept new connections by turn. Otherwise, all worker processes will be notified about new connections, and if volume of new connections is low, some of the worker processes may just waste system resources.
+    accept_mutex on;
+    # This directive determines how long a worker should wait before accepting a new connection. Once the accept_mutex is turned on, a mutex lock is assigned to a worker for a timeframe specified by the accept_mutex_delay . When the timeframe is up, the next worker in line is ready to accept new connections.
+    accept_mutex_delay 200ms;
+    # This directive specifies the method to process a connection from the client. We decided to set the value to epoll because we are working on a Ubuntu platform. The epoll method is the most effective processing method for Linux platforms.
+    use epoll;
+    # This specifies the number of events that NGINX will pass to the kernel.
+    epoll_events 1024;
+}
+
+http {
+    include /etc/nginx/mime.types;
+    default_type application/octet-stream;
+
+    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+    '$status $body_bytes_sent "$http_referer" '
+    '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log /var/log/nginx/access.log main;
+
+    sendfile on;
+    #tcp_nopush     on;
+
+    keepalive_timeout 65;
+
+    #gzip  on;
+    server_names_hash_bucket_size 64;
+    server_names_hash_max_size 512;
+
+    include /etc/nginx/conf.d/*.conf;
+   
+}

+ 100 - 0
docker/setting/general.conf

@@ -0,0 +1,100 @@
+# favicon.ico
+location = /public/favicon.ico {
+	log_not_found off;
+	access_log off;
+	error_log off;
+}
+
+# Disable directory listing
+location / {
+	autoindex  off;
+	try_files $uri $uri/ /index.html;
+}
+
+# assets, media, and Static File Caching while allowing safe files
+location ~* \.(?:css(\.map)?|js(\.map)?|ttf|ttc|otf|eot|woff2?|svgz?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv|pdf|docx?|dotx?|docm|dotm|xlsx?|xltx?|xlsm|xltm|pptx?|potx?|pptm|potm|ppsx?)$ {
+	add_header Access-Control-Allow-Origin "*";
+	add_header Cache-Control "public";
+	expires 365d;
+	# Nginx logs every request that hits the server to a log file. If you use analytics to monitor this, you may want to turn this functionality off. Simply edit the access_log directive:
+	access_log on;
+}
+
+# deny access to .htaccess files
+location ~ /\.ht {
+	deny  all;
+	error_log off;
+	log_not_found off;
+}
+
+# Deny access to hidden files (beginning with a period)
+location ~ /\. {
+	deny all;
+	error_log off;
+	log_not_found off;
+}
+
+
+location /video/ {
+	# To utilize operating system resources, set the value of this directive to on. sendfile transfers data between file descriptors within the OS kernel space without sending it to the application buffers. This directive will be used to serve small files.
+	sendfile       on;
+	# This directive enables multi-threading when set to on for write and read operation. Multi-threading is an execution model that allows multiple threads to execute separately from each other whilst sharing their hosting process resources.
+	aio            threads;
+	# This directive improves cache effectiveness by allowing read and write to be sent directly to the application.  directio is a filesystem feature of every modern operating system. This directive will be used to serve larger files like videos.
+	directio       8m;
+	# This directive assigns a block size value to the data transfer. It related to the directio  directive.
+	directio_alignment 1024;
+}
+
+# define error pages
+error_page 401 403 404  /index.html;
+location = /index.html {
+	root /opt/dist;
+	internal;
+}
+
+# redirect server error pages
+error_page   500 502 503 504  /index.html;
+location = / {
+	root   /opt/dist;
+	internal;
+}
+
+## Only GET, POST, PUT are allowed##
+if ($request_method !~ ^(GET|PUT|POST)$ ) {
+	return 444;
+}
+## In this case, it does not accept other HTTP method such as HEAD, DELETE, SEARCH, TRACE ##
+
+##  Only allow access to these domains/sub-domains samwanekeya.com and localhost
+# if ($host !~ ^(localhost|127.0.0.1|192.168.0.52|192.168.0.163)$ ) {
+# 	return 444;
+# }
+
+#Gzip can help reduce the amount of network transfer Nginx deals with. However, be careful increasing the gzip_comp_level too high as the server will begin wasting cpu cycles.
+#For those using Cloudflare as their CDN this is already taken care of - https://support.cloudflare.com/hc/en-us/articles/200168086-Does-Cloudflare-compress-resources-
+
+#If you want to enable compression, set the value of this directive to on. By default, it is disabled.
+gzip             on;
+# You can make use of this directive to set the compression level. In order not to waste CPU resources, you need not set the compression level too high. Between 1 and 9, you can set the compression level to 2 or 3.
+gzip_comp_level  2;
+# Set the minimum response length for compression via the content-length response header field. You can set it to more than 20 bytes.
+gzip_min_length  1000;
+gzip_proxied     expired no-cache no-store private auth;
+# This directive allows you to choose the response type you want to compress. By default, the response type text/html is always compressed. You can add other response type such as text/plain application/x-javascript text/xml as shown in the code above.
+# gzip_types       text/plain application/x-javascript text/xml text/css application/xml;
+# This directive allows you to choose the minimum HTTP version of a request for a compressed response. You can make use of the default value which is 1.1.
+#gzip_http_version 1.1;
+# When gzip directive is enabled, this directive add the header field Vary:Accept Encoding  to the response.
+#gzip_vary  on;
+# Some browsers such as Internet Explorer 6 do not have support for gzip compression. This directive make use of User-Agent request header field to disable compression for certain browsers.
+#gzip_disable "MSIE [4-6] \.";
+
+# This directive is disabled by default. Enable it if you want implement caching in Nginx. This directive stores metadata of files and directories commonly requested by users.
+open_file_cache max=1000 inactive=30s;
+# This directive contains backup information inside the open_file_cache directive. You can use this directive to set a valid period usually in seconds after which the information related to files and directories is re-validated again.
+open_file_cache_valid 30s;
+# Nginx usually clear information inside the open_file_cache directive after a period of inactivity based on the open_file_cache_min_uses. You can use this directive to set a minimum number of access to identify which files and directories are actively accessed.
+open_file_cache_min_uses 4;
+# You can make use of this directive to allow Nginx to cache errors  such as “permission denied” or “can’t access this file” when files are accessed. So anytime a resource is accessed by a user who does not have the right to do so, Nginx displays the same error report “permission denied”.
+open_file_cache_errors on;

+ 117 - 0
docker/setting/general_production.conf

@@ -0,0 +1,117 @@
+# favicon.ico
+location = /public/favicon.ico {
+	log_not_found off;
+	access_log off;
+	error_log off;
+}
+
+# Disable directory listing
+location / {
+	autoindex  off;
+	try_files $uri $uri/ /index.html;
+}
+
+# assets, media, and Static File Caching while allowing safe files
+# location ~* \.(?:css(\.map)?|js(\.map)?|ttf|ttc|otf|eot|woff2?|svgz?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv|pdf|docx?|dotx?|docm|dotm|xlsx?|xltx?|xlsm|xltm|pptx?|potx?|pptm|potm|ppsx?)$ {
+# 	add_header Access-Control-Allow-Origin "*";
+# 	add_header Cache-Control "public";
+# 	expires 365d;
+# 	# Nginx logs every request that hits the server to a log file. If you use analytics to monitor this, you may want to turn this functionality off. Simply edit the access_log directive:
+# 	access_log on;
+# }
+
+location ~* \.(ttf|ttc|otf|eot|woff2?|svgz?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv|pdf|docx?|dotx?|docm|dotm|xlsx?|xltx?|xlsm|xltm|pptx?|potx?|pptm|potm|ppsx?)$ {
+	add_header Access-Control-Allow-Origin "*";
+	add_header Cache-Control "public";
+	expires 365d;
+	# Nginx logs every request that hits the server to a log file. If you use analytics to monitor this, you may want to turn this functionality off. Simply edit the access_log directive:
+	access_log on;
+}
+
+location ~* \.(?:css(\.map)?|js(\.map))$ {
+	expires off;
+	add_header Cache-Control "no-cache";
+	# expires 365d;
+	# Nginx logs every request that hits the server to a log file. If you use analytics to monitor this, you may want to turn this functionality off. Simply edit the access_log directive:
+	access_log on;
+}
+
+
+# deny access to .htaccess files
+location ~ /\.ht {
+	deny  all;
+	error_log off;
+	log_not_found off;
+}
+
+# Deny access to hidden files (beginning with a period)
+location ~ /\. {
+	deny all;
+	error_log off;
+	log_not_found off;
+}
+
+
+location /video/ {
+	# To utilize operating system resources, set the value of this directive to on. sendfile transfers data between file descriptors within the OS kernel space without sending it to the application buffers. This directive will be used to serve small files.
+	sendfile       on;
+	# This directive enables multi-threading when set to on for write and read operation. Multi-threading is an execution model that allows multiple threads to execute separately from each other whilst sharing their hosting process resources.
+	aio            threads;
+	# This directive improves cache effectiveness by allowing read and write to be sent directly to the application.  directio is a filesystem feature of every modern operating system. This directive will be used to serve larger files like videos.
+	directio       8m;
+	# This directive assigns a block size value to the data transfer. It related to the directio  directive.
+	directio_alignment 1024;
+}
+
+# define error pages
+error_page 401 403 404  /index.html;
+location = /index.html {
+	root /opt/dist;
+	internal;
+}
+
+# redirect server error pages
+error_page   500 502 503 504  /index.html;
+location = / {
+	root   /opt/dist;
+	internal;
+}
+
+## Only GET, POST, PUT are allowed##
+if ($request_method !~ ^(GET|PUT|POST)$ ) {
+	return 444;
+}
+## In this case, it does not accept other HTTP method such as HEAD, DELETE, SEARCH, TRACE ##
+
+##  Only allow access to these domains/sub-domains samwanekeya.com and localhost
+# if ($host !~ ^(localhost|127.0.0.1|192.168.0.52|192.168.0.163)$ ) {
+# 	return 444;
+# }
+
+#Gzip can help reduce the amount of network transfer Nginx deals with. However, be careful increasing the gzip_comp_level too high as the server will begin wasting cpu cycles.
+#For those using Cloudflare as their CDN this is already taken care of - https://support.cloudflare.com/hc/en-us/articles/200168086-Does-Cloudflare-compress-resources-
+
+#If you want to enable compression, set the value of this directive to on. By default, it is disabled.
+gzip             on;
+# You can make use of this directive to set the compression level. In order not to waste CPU resources, you need not set the compression level too high. Between 1 and 9, you can set the compression level to 2 or 3.
+gzip_comp_level  2;
+# Set the minimum response length for compression via the content-length response header field. You can set it to more than 20 bytes.
+gzip_min_length  1000;
+gzip_proxied     expired no-cache no-store private auth;
+# This directive allows you to choose the response type you want to compress. By default, the response type text/html is always compressed. You can add other response type such as text/plain application/x-javascript text/xml as shown in the code above.
+# gzip_types       text/plain application/x-javascript text/xml text/css application/xml;
+# This directive allows you to choose the minimum HTTP version of a request for a compressed response. You can make use of the default value which is 1.1.
+#gzip_http_version 1.1;
+# When gzip directive is enabled, this directive add the header field Vary:Accept Encoding  to the response.
+#gzip_vary  on;
+# Some browsers such as Internet Explorer 6 do not have support for gzip compression. This directive make use of User-Agent request header field to disable compression for certain browsers.
+#gzip_disable "MSIE [4-6] \.";
+
+# This directive is disabled by default. Enable it if you want implement caching in Nginx. This directive stores metadata of files and directories commonly requested by users.
+open_file_cache max=1000 inactive=30s;
+# This directive contains backup information inside the open_file_cache directive. You can use this directive to set a valid period usually in seconds after which the information related to files and directories is re-validated again.
+open_file_cache_valid 30s;
+# Nginx usually clear information inside the open_file_cache directive after a period of inactivity based on the open_file_cache_min_uses. You can use this directive to set a minimum number of access to identify which files and directories are actively accessed.
+open_file_cache_min_uses 4;
+# You can make use of this directive to allow Nginx to cache errors  such as “permission denied” or “can’t access this file” when files are accessed. So anytime a resource is accessed by a user who does not have the right to do so, Nginx displays the same error report “permission denied”.
+open_file_cache_errors on;

+ 112 - 0
docker/setting/general_staging.conf

@@ -0,0 +1,112 @@
+# favicon.ico
+location = /public/favicon.ico {
+	log_not_found off;
+	access_log off;
+	error_log off;
+}
+
+# Disable directory listing
+location / {
+	autoindex off;
+	try_files $uri $uri/ /index.html;
+}
+
+# assets, media, and Static File Caching while allowing safe files
+location ~* \.(ttf|ttc|otf|eot|woff2?|svgz?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv|pdf|docx?|dotx?|docm|dotm|xlsx?|xltx?|xlsm|xltm|pptx?|potx?|pptm|potm|ppsx?)$ {
+	add_header Access-Control-Allow-Origin "*";
+	add_header Cache-Control "public";
+	expires 365d;
+	# Nginx logs every request that hits the server to a log file. If you use analytics to monitor this, you may want to turn this functionality off. Simply edit the access_log directive:
+	access_log on;
+}
+
+location ~* \.(?:css(\.map)?|js(\.map))$ {
+	expires off;
+	add_header Cache-Control "no-cache";
+	add_header Last-Modified "";
+	add_header ETag "";
+	# expires 365d;
+	# Nginx logs every request that hits the server to a log file. If you use analytics to monitor this, you may want to turn this functionality off. Simply edit the access_log directive:
+	access_log on;
+}
+
+
+# deny access to .htaccess files
+location ~ /\.ht {
+	deny all;
+	error_log off;
+	log_not_found off;
+}
+
+# Deny access to hidden files (beginning with a period)
+location ~ /\. {
+	deny all;
+	error_log off;
+	log_not_found off;
+}
+
+
+location /video/ {
+	# To utilize operating system resources, set the value of this directive to on. sendfile transfers data between file descriptors within the OS kernel space without sending it to the application buffers. This directive will be used to serve small files.
+	sendfile on;
+	# This directive enables multi-threading when set to on for write and read operation. Multi-threading is an execution model that allows multiple threads to execute separately from each other whilst sharing their hosting process resources.
+	aio threads;
+	# This directive improves cache effectiveness by allowing read and write to be sent directly to the application.  directio is a filesystem feature of every modern operating system. This directive will be used to serve larger files like videos.
+	directio 8m;
+	# This directive assigns a block size value to the data transfer. It related to the directio  directive.
+	directio_alignment 1024;
+}
+
+# define error pages
+error_page 401 403 404 /index.html;
+location = /index.html {
+	root /opt/dist;
+	internal;
+}
+
+# redirect server error pages
+error_page 500 502 503 504 /index.html;
+location = / {
+	root /opt/dist;
+	internal;
+}
+
+## Only GET, POST, PUT are allowed##
+if ($request_method !~ ^(GET|PUT|POST)$ ) {
+	return 444;
+}
+## In this case, it does not accept other HTTP method such as HEAD, DELETE, SEARCH, TRACE ##
+
+##  Only allow access to these domains/sub-domains samwanekeya.com and localhost
+# if ($host !~ ^(localhost|127.0.0.1|192.168.0.52|192.168.0.163)$ ) {
+# 	return 444;
+# }
+
+#Gzip can help reduce the amount of network transfer Nginx deals with. However, be careful increasing the gzip_comp_level too high as the server will begin wasting cpu cycles.
+#For those using Cloudflare as their CDN this is already taken care of - https://support.cloudflare.com/hc/en-us/articles/200168086-Does-Cloudflare-compress-resources-
+#If you want to enable compression, set the value of this directive to on. By default, it is disabled.
+gzip on;
+# You can make use of this directive to set the compression level. In order not to waste CPU resources, you need not set the compression level too high. Between 1 and 9, you can set the compression level to 2 or 3.
+gzip_comp_level 2;
+# Set the minimum response length for compression via the content-length response header field. You can set it to more than 20 bytes.
+gzip_min_length 1000;
+gzip_proxied expired no-cache no-store private auth;
+# This directive allows you to choose the response type you want to compress. By default, the response type text/html is always compressed. You can add other response type such as text/plain application/x-javascript text/xml as shown in the code above.
+# gzip_types       text/plain application/x-javascript text/xml text/css application/xml;
+# This directive allows you to choose the minimum HTTP version of a request for a compressed response. You can make use of the default value which is 1.1.
+#gzip_http_version 1.1;
+# When gzip directive is enabled, this directive add the header field Vary:Accept Encoding  to the response.
+#gzip_vary  on;
+# Some browsers such as Internet Explorer 6 do not have support for gzip compression. This directive make use of User-Agent request header field to disable compression for certain browsers.
+#gzip_disable "MSIE [4-6] \.";
+
+# This directive is disabled by default. Enable it if you want implement caching in Nginx. This directive stores metadata of files and directories commonly requested by users.
+open_file_cache max=1000 inactive=30s;
+# This directive contains backup information inside the open_file_cache directive. You can use this directive to set a valid period usually in seconds after which the information related to files and directories is re-validated again.
+open_file_cache_valid 30s;
+# Nginx usually clear information inside the open_file_cache directive after a period of inactivity based on the open_file_cache_min_uses. You can use this directive to set a minimum number of access to identify which files and directories are actively accessed.
+open_file_cache_min_uses 4;
+# You can make use of this directive to allow Nginx to cache errors  such as “permission denied” or “can’t access this file” when files are accessed. So anytime a resource is accessed by a user who does not have the right to do so, Nginx displays the same error report “permission denied”.
+open_file_cache_errors on;
+
+# 测试环境的一些

+ 8 - 0
docker/setting/proxy.conf

@@ -0,0 +1,8 @@
+location /basic-api/ {
+    proxy_pass http://192.168.0.47:8190/;
+}
+
+location /zfb-api/ {
+    # proxy_pass http://192.168.0.47:7081/;
+    proxy_pass http://192.168.0.47:7081/;
+}

+ 32 - 0
docker/setting/security.conf

@@ -0,0 +1,32 @@
+# config to don't allow the browser to render the page inside an frame or iframe
+# and avoid clickjacking http://en.wikipedia.org/wiki/Clickjacking
+# if you need to allow [i]frames, you can use SAMEORIGIN or even set an uri with ALLOW-FROM uri
+# https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options
+add_header X-Frame-Options "SAMEORIGIN";
+#Handled by CDN admin   
+# when serving user-supplied content, include a X-Content-Type-Options: nosniff header along with the Content-Type: header,
+# to disable content-type sniffing on some browsers.
+# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
+# currently suppoorted in IE > 8 http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx
+# http://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx
+# 'soon' on Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=471020
+add_header X-Content-Type-Options "nosniff";
+# This header enables the Cross-site scripting (XSS) filter built into most recent web browsers.
+# It's usually enabled by default anyway, so the role of this header is to re-enable the filter for
+# this particular website if it was disabled by the user.
+# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
+add_header X-XSS-Protection "1; mode=block";
+
+add_header Referrer-Policy "no-referrer-when-downgrade";
+# with Content Security Policy (CSP) enabled(and a browser that supports it(http://caniuse.com/#feat=contentsecuritypolicy),
+# you can tell the browser that it can only download content from the domains you explicitly allow
+# http://www.html5rocks.com/en/tutorials/security/content-security-policy/
+# https://www.owasp.org/index.php/Content_Security_Policy
+# I need to change our application code so we can increase security by disabling 'unsafe-inline' 'unsafe-eval'
+# directives for css and js(if you have inline css or js, you will need to keep it too).
+# more: http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful
+# add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'";
+#For Clouflare users comment this out as it's handle from the admin UI
+add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
+# Prevent search engine indexing
+add_header  X-Robots-Tag "noindex, nofollow, nosnippet, noarchive";

+ 48 - 0
docker/start.sh

@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+
+if [ ! -f ".env" ]; then
+    cp env.example .env
+fi
+
+if [ ! -z "$SXZ_HTTP_PORT" ] && [ ! -z "$CONTAINER_NAME" ]; then
+    echo "存在全局变量"
+    rm .env
+    cat >>.env <<EOF
+SXZ_HTTP_PORT=$SXZ_HTTP_PORT
+CONTAINER_NAME=$CONTAINER_NAME
+EOF
+    
+else
+    
+    echo "不存在全局变量"
+    source .env
+fi
+
+echo "http_port: $SXZ_HTTP_PORT"
+echo "container_name: $CONTAINER_NAME"
+
+
+if [ ! "$(docker ps -q -f name=$CONTAINER_NAME))" ]; then
+    if [ "$(docker ps -aq -f status=exited -f name=$CONTAINER_NAME))" ]; then
+        # cleanup
+        docker rm $CONTAINER_NAME -f
+    fi
+    # run your container
+    echo "no container and docker-compose up"
+    docker-compose up -d
+else
+    if [ "$(docker ps -aq -f status=running -f name=$CONTAINER_NAME))" ]; then
+        # cleanup
+        docker rm $CONTAINER_NAME -f
+    fi
+    echo "has container and docker-compose up"
+    $(which docker-compose) up -d
+    
+fi
+
+# if [ "$(docker container inspect -f '{{.State.Status}}' $CONTAINER_NAME)" == "running" ]; then
+#     docker rm $CONTAINER_NAME -f
+#     docker-compose up -d
+# else
+#     docker-compose up -d
+# fi

+ 2 - 2
mock/_util.ts

@@ -47,7 +47,7 @@ export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]
 export interface requestParams {
   method: string;
   body: any;
-  headers?: { authorization?: string };
+  headers?: { token?: string };
   query: any;
 }
 
@@ -56,5 +56,5 @@ export interface requestParams {
  *
  */
 export function getRequestToken({ headers }: requestParams): string | undefined {
-  return headers?.authorization;
+  return headers?.token;
 }

+ 39 - 0
mock/advertisement/selectAll.ts

@@ -0,0 +1,39 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 1200; index++) {
+    result.push({
+      id: `${index}`,
+      content: '@cparagraph(1, 3)',
+      createTime: '@datetime',
+      image: `@image('313x200', '@color', '示例slider')`,
+      orderNum: '@integer(0,10)',
+      title: '@ctitle(0,15)',
+      link: '@url',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/zfb-api/zfb/rotation/selectAll',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 39 - 0
mock/advertisement/selectId.ts

@@ -0,0 +1,39 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 1200; index++) {
+    result.push({
+      id: `${index}`,
+      content: '@cparagraph(1, 3)',
+      createTime: '@datetime',
+      image: `@image('313x200', '@color', '示例slider')`,
+      orderNum: '@integer(0,10)',
+      title: '@ctitle(0,15)',
+      url: null,
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/zfb-api/zfb/rotation/selectAll',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 1 - 1
mock/company/selectCompanyByType.ts

@@ -32,7 +32,7 @@ const demoList = (() => {
       memoName: '@ctitle(10,20)',
       name: '@ctitle(10,20)',
       phone: phone,
-      point: null,
+      point: '@integer(1,20)',
       qualification: null,
       sceneLogo: null,
       startTime: '@datetime',

+ 2 - 2
mock/company/selectCompanyNum.ts

@@ -66,9 +66,9 @@ const demoList = (() => {
 
 export default [
   {
-    url: '/basic-api/zfb/company/selectCompanyNum',
+    url: '/basic-api/mock/zfb/company/selectCompanyNum',
     timeout: 1000,
-    method: 'get',
+    method: 'post',
     response: ({ query }) => {
       const { page = 1, pageSize = 20 } = query;
       return resultPageSuccess(page, pageSize, demoList);

+ 2 - 2
mock/demo/account.ts

@@ -3,7 +3,7 @@ import { resultSuccess, resultError } from '../_util';
 import { ResultEnum } from '../../src/enums/httpEnum';
 
 const userInfo = {
-  name: 'Vben',
+  name: '4dage',
   userid: '00000001',
   email: 'test@gmail.com',
   signature: '海纳百川,有容乃大',
@@ -39,7 +39,7 @@ const userInfo = {
   notifyCount: 12,
   unreadCount: 11,
   country: 'China',
-  address: 'Xiamen City 77',
+  address: 'Zhuhai City 77',
   phone: '0592-268888888',
 };
 

+ 202 - 0
mock/demo/system.ts

@@ -0,0 +1,202 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { resultError, resultPageSuccess, resultSuccess } from '../_util';
+
+const accountList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 20; index++) {
+    result.push({
+      id: `${index}`,
+      account: '@first',
+      email: '@email',
+      nickname: '@cname()',
+      role: '@first',
+      createTime: '@datetime',
+      remark: '@cword(10,20)',
+      'status|1': ['0', '1'],
+    });
+  }
+  return result;
+})();
+
+const roleList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 4; index++) {
+    result.push({
+      id: index + 1,
+      orderNo: `${index + 1}`,
+      roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index],
+      roleValue: '@first',
+      createTime: '@datetime',
+      remark: '@cword(10,20)',
+      menu: [['0', '1', '2'], ['0', '1'], ['0', '2'], ['2']][index],
+      'status|1': ['0', '1'],
+    });
+  }
+  return result;
+})();
+
+const deptList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 3; index++) {
+    result.push({
+      id: `${index}`,
+      deptName: ['华东分部', '华南分部', '西北分部'][index],
+      orderNo: index + 1,
+      createTime: '@datetime',
+      remark: '@cword(10,20)',
+      'status|1': ['0', '0', '1'],
+      children: (() => {
+        const children: any[] = [];
+        for (let j = 0; j < 4; j++) {
+          children.push({
+            id: `${index}-${j}`,
+            deptName: ['研发部', '市场部', '商务部', '财务部'][j],
+            orderNo: j + 1,
+            createTime: '@datetime',
+            remark: '@cword(10,20)',
+            'status|1': ['0', '1'],
+            parentDept: `${index}`,
+            children: undefined,
+          });
+        }
+        return children;
+      })(),
+    });
+  }
+  return result;
+})();
+
+const menuList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 3; index++) {
+    result.push({
+      id: `${index}`,
+      icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index],
+      component: 'LAYOUT',
+      type: '0',
+      menuName: ['Dashboard', '权限管理', '功能'][index],
+      permission: '',
+      orderNo: index + 1,
+      createTime: '@datetime',
+      'status|1': ['0', '0', '1'],
+      children: (() => {
+        const children: any[] = [];
+        for (let j = 0; j < 4; j++) {
+          children.push({
+            id: `${index}-${j}`,
+            type: '1',
+            menuName: ['菜单1', '菜单2', '菜单3', '菜单4'][j],
+            icon: 'ion:document',
+            permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index],
+            component: [
+              '/dashboard/welcome/index',
+              '/dashboard/analysis/index',
+              '/dashboard/workbench/index',
+              '/dashboard/test/index',
+            ][j],
+            orderNo: j + 1,
+            createTime: '@datetime',
+            'status|1': ['0', '1'],
+            parentMenu: `${index}`,
+            children: (() => {
+              const children: any[] = [];
+              for (let k = 0; k < 4; k++) {
+                children.push({
+                  id: `${index}-${j}-${k}`,
+                  type: '2',
+                  menuName: '按钮' + (j + 1) + '-' + (k + 1),
+                  icon: '',
+                  permission:
+                    ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index] +
+                    ':btn' +
+                    (k + 1),
+                  component: [
+                    '/dashboard/welcome/index',
+                    '/dashboard/analysis/index',
+                    '/dashboard/workbench/index',
+                    '/dashboard/test/index',
+                  ][j],
+                  orderNo: j + 1,
+                  createTime: '@datetime',
+                  'status|1': ['0', '1'],
+                  parentMenu: `${index}-${j}`,
+                  children: undefined,
+                });
+              }
+              return children;
+            })(),
+          });
+        }
+        return children;
+      })(),
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/system/getAccountList',
+    timeout: 100,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, accountList);
+    },
+  },
+  {
+    url: '/basic-api/system/getRoleListByPage',
+    timeout: 100,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, roleList);
+    },
+  },
+  {
+    url: '/basic-api/system/setRoleStatus',
+    timeout: 500,
+    method: 'post',
+    response: ({ query }) => {
+      const { id, status } = query;
+      return resultSuccess({ id, status });
+    },
+  },
+  {
+    url: '/basic-api/system/getAllRoleList',
+    timeout: 100,
+    method: 'get',
+    response: () => {
+      return resultSuccess(roleList);
+    },
+  },
+  {
+    url: '/basic-api/system/getDeptList',
+    timeout: 100,
+    method: 'get',
+    response: () => {
+      return resultSuccess(deptList);
+    },
+  },
+  {
+    url: '/basic-api/system/getMenuList',
+    timeout: 100,
+    method: 'get',
+    response: () => {
+      return resultSuccess(menuList);
+    },
+  },
+  {
+    url: '/basic-api/system/accountExist',
+    timeout: 500,
+    method: 'post',
+    response: ({ body }) => {
+      const { account } = body || {};
+      if (account && account.indexOf('admin') !== -1) {
+        return resultError('该字段不能包含admin');
+      } else {
+        return resultSuccess(`${account} can use`);
+      }
+    },
+  },
+] as MockMethod[];

+ 81 - 0
mock/devices/pageList.ts

@@ -0,0 +1,81 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 1200; index++) {
+    const { phone } = mock({
+      phone: '@phone',
+    });
+    result.push({
+      id: `${index}`,
+      activatedTime: '@datetime',
+      address: '@city(true)',
+      agentFrameworkId: null,
+      agentFrameworkName: null,
+      agentName: null,
+      balance: 'THETAYP41136787.OSC',
+      'cameraType|1': [1, 4, 9, 10, 6],
+      childName: 'THETAYP41136787.OSC',
+      companyId: null,
+      companyName: '@ctitle',
+      cooperationUser: null,
+      cooperationUserName: null,
+      country: 0,
+      createTime: null,
+      goodsId: null,
+      goodsName: null,
+      imageUrl: null,
+      inTime: null,
+      isExpire: null,
+      lastTime: null,
+      nickName: null,
+      orderSn: null,
+      outTime: null,
+      'own|1': [0, 1, 2, 3],
+      pic: null,
+      recStatus: 'A',
+      responseUserIncrement: null,
+      sceneNum: null,
+      'snCode|8': '@integer(1,20)',
+      space: null,
+      spaceContent: null,
+      spaceEndStr: null,
+      spaceEndTime: null,
+      spaceId: null,
+      spaceStr: null,
+      surplusDate: null,
+      totalSpace: 0,
+      totalSpaceStr: null,
+      type: null,
+      usedSpace: 0,
+      usedSpaceStr: null,
+      userId: '@integer(1,20)',
+      userIncrementId: null,
+      userName: phone,
+      wifiName: 'THETAYP41136787.OSC',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/camera/pageList',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 43 - 0
mock/feedback/list.ts

@@ -0,0 +1,43 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 200; index++) {
+    const { phone } = mock({
+      phone: '@phone',
+    });
+
+    result.push({
+      id: `${index}`,
+      name: '@ctitle(5,15)',
+      nickName: '@ctitle(5,15)',
+      phone: phone,
+      'feedbackType|1': [0, 1, 2, 3, 4],
+      content: '@cparagraph(1, 3)',
+      createTime: '@datetime',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/feedback/list',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 85 - 0
mock/house/selectHouseByType.ts

@@ -0,0 +1,85 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 1200; index++) {
+    const { phone } = mock({
+      phone: '@phone',
+    });
+    result.push({
+      id: `${index}`,
+
+      // bgMusic: '@url()',
+      // cameraNum: '@integer(1,20)',
+      // childName: '@ctitle(10,20)',
+      // expirationDate: '@datetime',
+      // expirationTime: '@datetime',
+      // floorLogo: '@image()',
+      // name: '@ctitle(10,15)',
+      // num: '@integer(1,20)',
+      // point: '@integer(1,100)',
+      // sceneLogo: '@image()',
+      // sceneNum: '@integer(1,10)',
+      // subNum: '@integer(1,20)',
+      // userName: phone,
+
+      buildingId: '@integer(1,20)',
+      buildingNum: null,
+      companyName: '@ctitle(10,20)',
+      coveredArea: null,
+      createTime: '@datetime',
+      decorate: null,
+      elevator: null,
+      endTime: null,
+      floor: null,
+      head: null,
+      homepic: null,
+      houseNum: null,
+      latitude: null,
+      longitude: null,
+      name: '@ctitle(10,20)',
+      nickName: null,
+      orientation: null,
+      parlourNum: null,
+      phone: phone,
+      power: null,
+      price: null,
+      purpose: null,
+      roomNum: null,
+      sellTime: null,
+      startTime: null,
+      'state|1': ['0', '1'],
+      title: '@ctitle(10,15)',
+      toiletNum: null,
+      total: null,
+      type: null,
+      unitNum: null,
+      userName: phone,
+      userType: null,
+      utilizationArea: null,
+      website: null,
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/house/selectHouseByType',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 50 - 0
mock/member/list.ts

@@ -0,0 +1,50 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 200; index++) {
+    const { phone } = mock({
+      phone: '@phone',
+    });
+
+    result.push({
+      id: `${index}`,
+      name: '@cname',
+      nickName: '@cname',
+      avatarUrl: `@image('400x400', '@color', '微信头像')`,
+      'gender|1': [0, 1, 2],
+      city: '@city',
+      phone: phone,
+      province: '@province',
+      country: '@region',
+      language: '',
+      address: '@county(true)',
+      creatTime: '@datetime',
+      birthday: '@datetime',
+      lastLogin: '@datetime',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/member/list',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 71 - 0
mock/order/list.ts

@@ -0,0 +1,71 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 200; index++) {
+    const { phone } = mock({
+      phone: '@phone',
+    });
+    const { phone2 } = mock({
+      phone2: '@phone',
+    });
+    result.push({
+      id: `${index}`,
+      'orderNo|23': '@integer(0,9)',
+      name: '@ctitle(5,15)',
+      'orderType|1': [0, 1, 2, 3],
+      'orderStatus|1': [0, 1, 2, 3],
+      'shipingStatus|1': [0, 1],
+      'paymentStatus|1': [0, 1],
+      'shipingCompany|1': [
+        '顺丰速运',
+        'EMS',
+        '韵达快递',
+        '百世快递',
+        '申通快递',
+        '中通快递',
+        '韵达快递',
+      ],
+      'shipingNo|28': '@integer(5,15)',
+      'shipingAmount|2': '@integer(1,15)',
+      shipingName: '@cname',
+      shipingPhone: phone,
+
+      shipingAddress: '@city(true)',
+      deliverName: '@cname',
+      deliverPhone: phone2,
+      deliverAddress: '@city(true)',
+      scene: {
+        'id|1': '@integer(1,15)',
+        name: '@ctitle(5,15)',
+      },
+      'amount|3': '@integer(1,15)',
+      'totalAmount|3': '@integer(1,15)',
+      createTime: '@datetime',
+      paidTime: '@datetime',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/order/list',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 73 - 0
mock/product/category.ts

@@ -0,0 +1,73 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const categoryList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 20; index++) {
+    result.push({
+      id: `${index}`,
+      icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index],
+      component: 'LAYOUT',
+      name: '@ctitle(5,15)',
+      type: '0',
+      orderNo: index + 1,
+      createTime: '@datetime',
+      'status|1': ['0', '0', '1'],
+      children: (() => {
+        const children: any[] = [];
+        for (let j = 0; j < 4; j++) {
+          children.push({
+            id: `${index}-${j}`,
+            type: '1',
+            name: '@ctitle(5,15)',
+            icon: 'ion:document',
+            orderNo: j + 1,
+            createTime: '@datetime',
+            'status|1': ['0', '1'],
+            parentMenu: `${index}`,
+            children: (() => {
+              const children: any[] = [];
+              for (let k = 0; k < 4; k++) {
+                children.push({
+                  id: `${index}-${j}-${k}`,
+                  type: '2',
+                  name: '@ctitle(5,15)' + (j + 1) + '-' + (k + 1),
+                  icon: '',
+                  orderNo: j + 1,
+                  createTime: '@datetime',
+                  'status|1': ['0', '1'],
+                  parentMenu: `${index}-${j}`,
+                  children: undefined,
+                });
+              }
+              return children;
+            })(),
+          });
+        }
+        return children;
+      })(),
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/product/category',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, categoryList);
+    },
+  },
+] as MockMethod[];

+ 51 - 0
mock/product/list.ts

@@ -0,0 +1,51 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 200; index++) {
+    // const { phone } = mock({
+    //   phone: '@phone',
+    // });
+
+    result.push({
+      id: `${index}`,
+      name: '@ctitle(3,10)',
+      desc: '@cparagraph(3, 5)',
+      link: `https://zfb.4dkankan.com/smobile.html?m=@string( 'lower/number',5,10)`,
+      'productType|1': [0, 1, 2, 3],
+      steamRoom: {
+        id: 1,
+        name: '李嘉琪的直播间',
+      },
+      'amount|1': '@integer(20,50)',
+      'total|1': '@integer(20,50)',
+      'marketingUnit|1': '@float(20,50,3,4)',
+      'unit|1': '@float(20,50,3,6)',
+      isLaunched: '@boolean(1, 9, true)',
+      createTime: '@datetime',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/product/list',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 38 - 0
mock/scene/list.ts

@@ -0,0 +1,38 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 200; index++) {
+    result.push({
+      id: `${index}`,
+      name: '@ctitle(5,15)',
+      cover: `@image('313x200', '@color', 'demo封面')`,
+      link: `https://zfb.4dkankan.com/smobile.html?m=@string( 'lower/number',5,10)`,
+      createTime: '@datetime',
+      isShow: '@boolean(1, 9, true)',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/scene/list',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 44 - 0
mock/scene/live.ts

@@ -0,0 +1,44 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 200; index++) {
+    result.push({
+      id: `${index}`,
+      name: '@ctitle(5,15)',
+      cover: `@image('313x200', '@color', 'demo封面')`,
+      'houseType|1': [0, 1, 2, 3, 4],
+      'order|1': '@integer(1,200)',
+      hoster: {
+        'id|1': '@integer(1,100)',
+        name: '@cname',
+      },
+      link: `https://zfb.4dkankan.com/smobile.html?m=@string( 'lower/number',5,10)`,
+      createTime: '@datetime',
+      isSteam: '@boolean(1, 9, true)',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/scene/live',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 43 - 0
mock/staff/list.ts

@@ -0,0 +1,43 @@
+import { MockMethod } from 'vite-plugin-mock';
+import { mock, Random } from 'mockjs';
+import { resultPageSuccess } from '../_util';
+Random.extend({
+  phone: function () {
+    const phonePrefixs = ['132', '135', '189']; // 自己写前缀哈
+    return this.pick(phonePrefixs) + mock(/\d{8}/); //Number()
+  },
+});
+// console.log(Random.phone());
+// 生成 1 - 10 个 随机手机号码
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 200; index++) {
+    const { phone } = mock({
+      phone: '@phone',
+    });
+
+    result.push({
+      id: `${index}`,
+      name: '@cname',
+      company: '@ctitle(3,8)有限公司',
+      phone: phone,
+      'status|1': [0, 1],
+      'role|1': [0, 1],
+      createTime: '@datetime',
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/basic-api/zfb/staff/list',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];

+ 38 - 2
mock/sys/user.ts

@@ -35,6 +35,42 @@ export function createFakeUserList() {
         },
       ],
     },
+    {
+      userId: '3',
+      username: '用户17324327132',
+      password: '123456',
+      realName: 'test user',
+      avatar: 'https://q1.qlogo.cn/g?b=qq&nk=339449197&s=640',
+      desc: 'tester',
+      token: 'fakeToken2',
+      homePath: '/dashboard/workbench',
+      roles: [
+        {
+          roleName: 'Tester',
+          value: 'test',
+        },
+      ],
+      brandList: null,
+      canShow: null,
+      createTime: 1604981038000,
+      createUserId: 1,
+      deptExpirationDate: 1727625600000,
+      deptId: 193,
+      deptManagerPhoneNum: null,
+      deptName: 'hangtest',
+      email: null,
+      fdkkPassword: null,
+      fdkkUser: '15915816041',
+      isPlatformStreamer: false,
+      mobile: '17324327132',
+      parentDeptId: 1,
+      parentDeptName: null,
+      roleId: null,
+      roleIdList: null,
+      roleList: null,
+      roleName: null,
+      status: 1,
+    },
   ];
 }
 
@@ -46,7 +82,7 @@ const fakeCodeList: any = {
 export default [
   // mock user login
   {
-    url: '/basic-api/login',
+    url: '/basic-api/mock/login',
     timeout: 200,
     method: 'post',
     response: ({ body }) => {
@@ -74,7 +110,7 @@ export default [
     response: (request: requestParams) => {
       const token = getRequestToken(request);
       if (!token) return resultError('Invalid token');
-      const checkUser = createFakeUserList().find((item) => item.token === token);
+      const checkUser = createFakeUserList().find((item) => item.userId === '3');
       if (!checkUser) {
         return resultError('The corresponding user information was not obtained!');
       }

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 41054
package-lock.json


+ 98 - 67
package.json

@@ -1,18 +1,14 @@
 {
-  "name": "vben-admin",
-  "version": "2.8.0",
-  "author": {
-    "name": "vben",
-    "email": "anncwb@126.com",
-    "url": "https://github.com/anncwb"
-  },
+  "name": "zfb-mp",
+  "version": "4.0.0",
   "scripts": {
-    "bootstrap": "yarn install",
+    "bootstrap": "pnpm install",
     "serve": "npm run dev",
     "dev": "vite",
     "build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
+    "build:dev": "cross-env NODE_ENV=development vite build && esno ./build/script/postBuild.ts",
     "build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts",
-    "build:no-cache": "yarn clean:cache && npm run build",
+    "build:no-cache": "pnpm clean:cache && npm run build",
     "report": "cross-env REPORT=true npm run build",
     "type:check": "vue-tsc --noEmit --skipLibCheck",
     "preview": "npm run build && vite preview",
@@ -23,131 +19,166 @@
     "lint:eslint": "eslint --cache --max-warnings 0  \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
     "lint:prettier": "prettier --write  \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
     "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
-    "lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
+    "lint:lint-staged": "lint-staged",
     "test:unit": "jest",
     "test:unit-coverage": "jest --coverage",
     "test:gzip": "npx http-server dist --cors --gzip -c-1",
     "test:br": "npx http-server dist --cors --brotli -c-1",
-    "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
-    "prepare": "husky install",
+    "reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
+    "prepare": "node -e \"if(require('fs').existsSync('.git')){process.exit(1)}\" || husky install",
     "gen:icon": "esno ./build/generate/icon/index.ts"
   },
   "dependencies": {
     "@ant-design/colors": "^6.0.0",
     "@ant-design/icons-vue": "^6.0.1",
-    "@iconify/iconify": "^2.0.4",
-    "@vueuse/core": "^6.7.4",
-    "@vueuse/shared": "^6.7.4",
-    "@zxcvbn-ts/core": "^1.0.0-beta.0",
-    "ant-design-vue": "2.2.8",
+    "@iconify/iconify": "^2.1.0",
+    "@logicflow/core": "^0.7.16",
+    "@logicflow/extension": "^0.7.16",
+    "@vue/runtime-core": "^3.2.26",
+    "@vue/shared": "^3.2.26",
+    "@vueuse/core": "^7.4.1",
+    "@vueuse/shared": "^7.4.1",
+    "@zxcvbn-ts/core": "^1.2.0",
+    "ant-design-vue": "3.0.0-beta.7",
     "axios": "^0.24.0",
-    "crypto-js": "^4.1.1",
+    "codemirror": "^5.65.0",
     "cropperjs": "^1.5.12",
+    "crypto-js": "^4.1.1",
+    "dayjs": "^1.10.7",
     "echarts": "^5.2.2",
+    "intro.js": "^4.3.0",
+    "js-base64": "^3.7.2",
     "lodash-es": "^4.17.21",
     "mockjs": "^1.1.0",
     "moment": "^2.29.1",
     "nprogress": "^0.2.0",
     "path-to-regexp": "^6.2.0",
-    "pinia": "2.0.0",
-    "qrcode": "^1.4.4",
-    "qs": "^6.10.1",
+    "pinia": "2.0.9",
+    "print-js": "^1.6.0",
+    "qrcode": "^1.5.0",
+    "qs": "^6.10.2",
     "resize-observer-polyfill": "^1.5.1",
+    "showdown": "^1.9.1",
     "sortablejs": "^1.14.0",
-    "vue": "^3.2.21",
+    "tinymce": "^5.10.2",
+    "vditor": "^3.8.10",
+    "vue": "^3.2.26",
     "vue-i18n": "^9.1.9",
+    "vue-json-pretty": "^1.8.2",
     "vue-router": "^4.0.12",
-    "vue-types": "^4.1.1"
+    "vue-types": "^4.1.1",
+    "xlsx": "^0.17.4"
   },
   "devDependencies": {
-    "@commitlint/cli": "^14.1.0",
-    "@commitlint/config-conventional": "^14.1.0",
-    "@iconify/json": "^1.1.422",
+    "@commitlint/cli": "^16.0.1",
+    "@commitlint/config-conventional": "^16.0.0",
+    "@iconify/json": "^2.0.16",
     "@purge-icons/generated": "^0.7.0",
     "@types/codemirror": "^5.60.5",
     "@types/crypto-js": "^4.0.2",
     "@types/fs-extra": "^9.0.13",
     "@types/inquirer": "^8.1.3",
     "@types/intro.js": "^3.0.2",
-    "@types/jest": "^27.0.2",
+    "@types/jest": "^27.0.3",
     "@types/lodash-es": "^4.17.5",
     "@types/mockjs": "^1.0.4",
-    "@types/node": "^16.11.6",
+    "@types/node": "^17.0.5",
     "@types/nprogress": "^0.2.0",
-    "@types/qrcode": "^1.4.1",
+    "@types/qrcode": "^1.4.2",
     "@types/qs": "^6.9.7",
     "@types/showdown": "^1.9.4",
     "@types/sortablejs": "^1.10.7",
-    "@typescript-eslint/eslint-plugin": "^5.3.0",
-    "@typescript-eslint/parser": "^5.3.0",
-    "@vitejs/plugin-legacy": "^1.6.2",
-    "@vitejs/plugin-vue": "^1.9.4",
-    "@vitejs/plugin-vue-jsx": "^1.2.0",
-    "@vue/compiler-sfc": "3.2.21",
-    "@vue/test-utils": "^2.0.0-rc.16",
+    "@typescript-eslint/eslint-plugin": "^5.8.1",
+    "@typescript-eslint/parser": "^5.8.1",
+    "@vitejs/plugin-legacy": "^1.6.4",
+    "@vitejs/plugin-vue": "^2.0.1",
+    "@vitejs/plugin-vue-jsx": "^1.3.3",
+    "@vue/compiler-sfc": "3.2.26",
+    "@vue/test-utils": "^2.0.0-rc.18",
     "autoprefixer": "^10.4.0",
     "commitizen": "^4.2.4",
-    "conventional-changelog-cli": "^2.1.1",
+    "conventional-changelog-cli": "^2.2.2",
     "cross-env": "^7.0.3",
     "dotenv": "^10.0.0",
-    "eslint": "^8.1.0",
+    "eslint": "^8.5.0",
     "eslint-config-prettier": "^8.3.0",
-    "eslint-define-config": "^1.1.2",
-    "eslint-plugin-jest": "^25.2.2",
+    "eslint-define-config": "^1.2.1",
+    "eslint-plugin-jest": "^25.3.2",
     "eslint-plugin-prettier": "^4.0.0",
-    "eslint-plugin-vue": "^8.0.3",
-    "esno": "^0.10.1",
+    "eslint-plugin-vue": "^8.2.0",
+    "esno": "^0.13.0",
     "fs-extra": "^10.0.0",
     "husky": "^7.0.4",
     "inquirer": "^8.2.0",
-    "jest": "^27.3.1",
+    "jest": "^27.4.5",
     "less": "^4.1.2",
-    "lint-staged": "11.2.6",
+    "lint-staged": "12.1.4",
     "npm-run-all": "^4.1.5",
-    "postcss": "^8.3.11",
-    "postcss-html": "^1.2.0",
+    "postcss": "^8.4.5",
+    "postcss-html": "^1.3.0",
     "postcss-less": "^5.0.0",
-    "prettier": "^2.4.1",
+    "prettier": "^2.5.1",
     "rimraf": "^3.0.2",
     "rollup-plugin-visualizer": "^5.5.2",
-    "stylelint": "^14.0.1",
+    "stylelint": "^14.2.0",
     "stylelint-config-html": "^1.0.0",
     "stylelint-config-prettier": "^9.0.3",
-    "stylelint-config-standard": "^23.0.0",
+    "stylelint-config-recommended": "^6.0.0",
+    "stylelint-config-standard": "^24.0.0",
     "stylelint-order": "^5.0.0",
-    "ts-jest": "^27.0.7",
+    "ts-jest": "^27.1.2",
     "ts-node": "^10.4.0",
-    "typescript": "^4.4.4",
-    "vite": "^2.6.13",
-    "vite-plugin-compression": "^0.3.5",
-    "vite-plugin-html": "^2.1.1",
-    "vite-plugin-imagemin": "^0.4.6",
+    "typescript": "^4.5.4",
+    "vite": "^2.8.5",
+    "vite-plugin-compression": "^0.4.0",
+    "vite-plugin-html": "^2.1.2",
+    "vite-plugin-imagemin": "^0.5.1",
     "vite-plugin-mock": "^2.9.6",
     "vite-plugin-purge-icons": "^0.7.0",
-    "vite-plugin-pwa": "^0.11.3",
-    "vite-plugin-style-import": "^1.3.0",
+    "vite-plugin-pwa": "^0.11.12",
+    "vite-plugin-rewrite-all": "^0.1.2",
+    "vite-plugin-style-import": "^1.4.1",
     "vite-plugin-svg-icons": "^1.0.5",
     "vite-plugin-theme": "^0.8.1",
-    "vite-plugin-vue-setup-extend": "^0.1.0",
-    "vite-plugin-windicss": "^1.4.12",
+    "vite-plugin-vue-setup-extend": "^0.3.0",
+    "vite-plugin-windicss": "^1.6.1",
     "vue-eslint-parser": "^8.0.1",
-    "vue-tsc": "^0.28.10"
+    "vue-tsc": "^0.30.1"
   },
   "resolutions": {
-    "//": "Used to install imagemin dependencies, because imagemin may not be installed in China. If it is abroad, you can delete it",
     "bin-wrapper": "npm:bin-wrapper-china",
-    "rollup": "^2.56.3"
+    "rollup": "^2.56.3",
+    "gifsicle": "5.2.0"
   },
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/anncwb/vue-vben-admin.git"
+    "url": "git+http://face3d.4dage.com:7005/zhangyupeng/zfb_mp.git "
   },
   "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/anncwb/vue-vben-admin/issues"
-  },
-  "homepage": "https://github.com/anncwb/vue-vben-admin",
   "engines": {
     "node": "^12 || >=14"
+  },
+  "lint-staged": {
+    "*.{js,jsx,ts,tsx}": [
+      "eslint --fix",
+      "prettier --write"
+    ],
+    "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
+      "prettier --write--parser json"
+    ],
+    "package.json": [
+      "prettier --write"
+    ],
+    "*.vue": [
+      "eslint --fix",
+      "prettier --write"
+    ],
+    "*.{scss,less,styl,html}": [
+      "stylelint --fix",
+      "prettier --write"
+    ],
+    "*.md": [
+      "prettier --write"
+    ]
   }
 }

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 5053 - 7891
pnpm-lock.yaml


BIN
public/resource/img/logo.png


BIN
public/resource/img/logo1 (2).png


BIN
public/resource/img/pic_bg@2x.png


+ 1 - 0
src/App.vue

@@ -12,6 +12,7 @@
   import { useTitle } from '/@/hooks/web/useTitle';
   import { useLocale } from '/@/locales/useLocale';
 
+  import 'dayjs/locale/zh-cn';
   // support Multi-language
   const { getAntdLocale } = useLocale();
 

+ 16 - 0
src/api/account/index.ts

@@ -0,0 +1,16 @@
+import { defHttp } from '/@/utils/http/axios';
+import { GetAccountInfoModel } from './model';
+
+enum Api {
+  ACCOUNT_INFO = '/basic-api/account/getAccountInfo',
+  SESSION_TIMEOUT = '/basic-api/user/sessionTimeout',
+  TOKEN_EXPIRED = '/basic-api/user/tokenExpired',
+}
+
+// Get personal center-basic settings
+
+export const accountInfoApi = () => defHttp.get<GetAccountInfoModel>({ url: Api.ACCOUNT_INFO });
+
+export const sessionTimeoutApi = () => defHttp.post<void>({ url: Api.SESSION_TIMEOUT });
+
+export const tokenExpiredApi = () => defHttp.post<void>({ url: Api.TOKEN_EXPIRED });

+ 7 - 0
src/api/account/model.ts

@@ -0,0 +1,7 @@
+export interface GetAccountInfoModel {
+  email: string;
+  name: string;
+  introduction: string;
+  phone: string;
+  address: string;
+}

+ 112 - 0
src/api/advertisement/list.ts

@@ -0,0 +1,112 @@
+import { defHttp } from '/@/utils/http/axios';
+import { PageParams, ListGetResultModel, UpdateItem, DeleteItem } from './model';
+import { Result, UploadFileParams } from '/#/axios';
+
+enum Api {
+  selectAll = '/zfb-api/zfb/rotation/selectAll',
+  recommend = '/zfb-api/zfb/recommend/selectByType',
+  update = '/zfb-api/zfb/rotation/update',
+  save = '/zfb-api/zfb/rotation/save',
+  delete = '/zfb-api/zfb/rotation/delete',
+  uploadFile = '/zfb-api/zfb/house/upload',
+  padssave = '/zfb-api/zfb/recommend/save',
+  padsupdate = '/zfb-api/zfb/recommend/update',
+  padsdelete = '/zfb-api/zfb/recommend/delete',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const ListApi = (params: PageParams) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.selectAll,
+    params,
+
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const RecommendDeleteApi = (params: DeleteItem) =>
+  defHttp.post<Result>({
+    url: Api.padsdelete,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const RecommendListApi = (params: DeleteItem) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.recommend,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const itemUpdateApi = (params: UpdateItem) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.update,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const itemSaveApi = (params: UpdateItem) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.save,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const itemDeletelApi = (params: DeleteItem) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.delete,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export function uploadApi(
+  params: UploadFileParams,
+  // onUploadProgress: (progressEvent: ProgressEvent) => void,
+) {
+  return defHttp.uploadFile<Result>(
+    {
+      url: Api.uploadFile,
+      // onUploadProgress,
+    },
+    params,
+  );
+}
+
+export const padsUpdateApi = (params: UpdateItem) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.padsupdate,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const padsSaveApi = (params: UpdateItem) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.padssave,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 42 - 0
src/api/advertisement/model.ts

@@ -0,0 +1,42 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+
+export interface ListItem {
+  id: number;
+  content: string;
+  createTime: string;
+  image: string;
+  orderNum: number;
+  title: string;
+  url: string;
+}
+
+export interface UpdateItem {
+  content: string;
+  id: number;
+  image: string;
+  orderNum: number;
+  title: string;
+  url?: string;
+}
+
+export interface PadsItem {
+  connectId: number;
+  type: number;
+  id: number;
+  image: string;
+  orderNum: string;
+  title: string;
+  url?: string;
+}
+export interface DeleteItem {
+  id: number;
+}
+
+/**
+ * @description: Request list return value
+ */
+export type ListGetResultModel = BasicFetchResult<ListItem>;

+ 20 - 0
src/api/bulletin/model.ts

@@ -0,0 +1,20 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+export interface DeleteParams {
+  id: number;
+}
+
+export interface ListItem {
+  id: number;
+  name: string;
+  companyName: string;
+  state: string;
+}
+
+/**
+ * @description: Request list return value
+ */
+export type RentListGetResultModel = BasicFetchResult<ListItem>;

+ 63 - 0
src/api/bulletin/rent.ts

@@ -0,0 +1,63 @@
+import { defHttp } from '/@/utils/http/axios';
+import { PageParams, RentListGetResultModel, DeleteParams } from './model';
+
+enum Api {
+  selectHouseByType = '/zfb-api/zfb/house/selectHouseByType',
+  deleteHouse = '/zfb-api/zfb/house/deleteHouse',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const rentListApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.selectHouseByType,
+    params: {
+      type: 1,
+      ...params,
+    },
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const sellListApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.selectHouseByType,
+    params: {
+      type: 2,
+      ...params,
+    },
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const decorationListApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.selectHouseByType,
+    params: {
+      type: 0,
+      ...params,
+    },
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const commonDeleteApi = (params: DeleteParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.deleteHouse,
+    params: {
+      type: 0,
+      ...params,
+    },
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 111 - 3
src/api/corporation/list.ts

@@ -1,8 +1,24 @@
 import { defHttp } from '/@/utils/http/axios';
-import { PageParams, CorporationListGetResultModel } from './model';
+import {
+  PageParams,
+  CorporationListGetResultModel,
+  UpdateCompanyParam,
+  DeviceListItem,
+  DeviceGetResultModel,
+  SaveCompanyParam,
+} from './model';
+
+import { Result, UploadFileParams } from '/#/axios';
 
 enum Api {
-  selectCompanyNum = '/zfb/company/selectCompanyNum',
+  selectCompanyNum = '/zfb-api/zfb/company/selectCompanyNum',
+  listAllCompany = '/zfb-api/zfb/company/getListAll',
+  selectCompanyByType = '/zfb-api/zfb/company/selectCompanyByType',
+  uploadLogo = '/zfb-api/zfb/company/uploadLogo',
+  saveCompany = '/zfb-api/zfb/company/back/save',
+  updateCompany = '/zfb-api/zfb/company/updateCompany',
+  selectCompanyDevice = '/zfb-api/zfb/company/selectCompanyDevice',
+  unbindDevice = '/zfb-api/zfb/company/unbindDevice',
 }
 
 /**
@@ -10,7 +26,7 @@ enum Api {
  */
 
 export const ListApi = (params: PageParams) =>
-  defHttp.get<CorporationListGetResultModel>({
+  defHttp.post<CorporationListGetResultModel>({
     url: Api.selectCompanyNum,
     params,
     headers: {
@@ -18,3 +34,95 @@ export const ListApi = (params: PageParams) =>
       ignoreCancelToken: true,
     },
   });
+
+export const ListAllCompanyApi = (params: PageParams) =>
+  defHttp.post<CorporationListGetResultModel>({
+    url: Api.listAllCompany,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const ListVerifyApi = (params: PageParams) =>
+  defHttp.post<CorporationListGetResultModel>({
+    url: Api.selectCompanyByType,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const selectCompanyDevice = (params: UpdateCompanyParam) =>
+  defHttp.post<Result>({
+    url: Api.updateCompany,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const updateCompnayApi = (params: UpdateCompanyParam) =>
+  defHttp.post<Result>({
+    url: Api.updateCompany,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const saveCompanyApi = (params: SaveCompanyParam) =>
+  defHttp.post<Result>({
+    url: Api.saveCompany,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const ListCompanyDeviceApi = (params: DeviceListItem) =>
+  defHttp.post<DeviceGetResultModel>({
+    url: Api.selectCompanyDevice,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const unDeviceApi = (params: DeviceListItem) =>
+  defHttp.post<DeviceGetResultModel>({
+    url: Api.unbindDevice,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export function uploadLogoApi(
+  params: UploadFileParams,
+  // onUploadProgress: (progressEvent: ProgressEvent) => void,
+) {
+  return defHttp.uploadFile<Result>(
+    {
+      url: Api.uploadLogo,
+      // onUploadProgress,
+    },
+    params,
+  );
+}
+// export function uploadMusicApi(
+//   params: UploadFileParams,
+//   // onUploadProgress: (progressEvent: ProgressEvent) => void,
+// ) {
+//   return defHttp.uploadFile<Result>(
+//     {
+//       url: Api.uploadMusic,
+//       // onUploadProgress,
+//     },
+//     params,
+//   );
+// }

+ 104 - 0
src/api/corporation/modal.ts

@@ -0,0 +1,104 @@
+import { defHttp } from '/@/utils/http/axios';
+import {
+  selectUserListParam,
+  checkDeiceParam,
+  addDeiceParam,
+  checkUserParam,
+  SubAccountUsers,
+  selectCompanyParam,
+  auditParam,
+  addPointParam,
+} from './model';
+import type { Result } from '/#/axios';
+
+enum Api {
+  addDevice = '/zfb-api/zfb/company/addDevice',
+  checkDevice = '/zfb-api/zfb/company/checkDevice',
+  selectUserList = '/zfb-api/zfb/company/selectUserList',
+  addPoint = '/zfb-api/zfb/company/addPoint',
+  checkUserAddAble = '/zfb-api/zfb/company/back/checkUserAddAble',
+  saveSubUsers = '/zfb-api/zfb/company/saveSubUsers',
+  selectCompanyById = '/zfb-api/zfb/company/selectCompanyById',
+  auditCompany = '/zfb-api/zfb/company/auditCompany',
+}
+/**
+ * @description: Get sample list value
+ */
+
+export const AddDevice = (params: addDeiceParam) =>
+  defHttp.post<Result>({
+    url: Api.addDevice,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const checkDevice = (params: checkDeiceParam) =>
+  defHttp.post<Result>({
+    url: Api.checkDevice,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const auditCompany = (params: auditParam) =>
+  defHttp.post<Result>({
+    url: Api.auditCompany,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const addPoint = (params: addPointParam) =>
+  defHttp.post<Result>({
+    url: Api.addPoint,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const selectUserList = (params: selectUserListParam) =>
+  defHttp.post<Result>({
+    url: Api.selectUserList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const checkUserAddAble = (params: checkUserParam) =>
+  defHttp.post<Result>({
+    url: Api.checkUserAddAble,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const selectCompanyById = (params: selectCompanyParam) =>
+  defHttp.post<Result>({
+    url: Api.selectCompanyById,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const saveSubUsers = (params: SubAccountUsers) =>
+  defHttp.post<Result>({
+    url: Api.saveSubUsers,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 100 - 0
src/api/corporation/model.ts

@@ -3,6 +3,83 @@ import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
  * @description: Request list interface parameters
  */
 export type PageParams = BasicPageParams;
+export interface UpdateCompanyParam {
+  id: number;
+  sceneLogo?: string;
+  floorLogo?: string;
+  bgMusic?: string;
+  expirationTime?: string;
+}
+export interface SaveCompanyParam {
+  address?: string;
+  area?: string;
+  contacts?: string;
+  introduce?: string;
+  logo?: string;
+  name?: string;
+  phone?: string;
+  qualification?: string;
+  website?: string;
+}
+export interface addDeiceParam {
+  childNames: string | null;
+  id: number;
+  subNum: number;
+  userName: string;
+}
+export interface checkDeiceParam {
+  childName: string | null;
+}
+export interface auditParam {
+  state: number | null;
+  id: number | string;
+}
+
+export interface addPointParam {
+  id: number | null;
+  idpoint: number | null;
+}
+export interface selectUserListParam {
+  id: number | null;
+  page: number | null;
+  limit: number | null;
+}
+export interface checkUserParam {
+  phone: string | null;
+}
+
+export interface SubAccountUsers {
+  id: number | null;
+  subNum?: string | number;
+  shotNum: string | number;
+  lookNum: string | number;
+  subUsers: Recordable<any>[]; //SubAccountUser[];
+}
+
+export interface selectCompanyParam {
+  id: number | null;
+}
+export interface SubAccountUser {
+  appid: string | number | null;
+  companyId: string | number | null;
+  createTime: string | number | null;
+  createUser: string | number | null;
+  fdkkPassword: string | number | null;
+  fdkkUser: string | number | null;
+  head: string | number | null;
+  id: number | null;
+  memoName: string | null;
+  message: string | number | null;
+  nickName: string | null;
+  phone: string | null;
+  state: string | number | null;
+  token: string | number | null;
+  type: string | number | null;
+  updateTime: string | number | null;
+  updateUser: string | number | null;
+  userName: string | null;
+  userPassword: string | number | null;
+}
 
 export interface ListItem {
   id: number;
@@ -20,8 +97,31 @@ export interface ListItem {
   subNum: string;
   userName: string;
 }
+export interface ListItem {
+  id: number;
+  bgMusic: string;
+  cameraNum: string;
+  childName: string;
+  expirationDate: string;
+  expirationTime: string;
+  floorLogo: string;
+  name: string;
+  num: string;
+  point: string;
+  sceneLogo: string;
+  sceneNum: string;
+  subNum: string;
+  userName: string;
+}
+
+export interface DeviceListItem {
+  activeTime?: number;
+  childName?: string;
+  id?: number;
+}
 
 /**
  * @description: Request list return value
  */
 export type CorporationListGetResultModel = BasicFetchResult<ListItem>;
+export type DeviceGetResultModel = BasicFetchResult<DeviceListItem>;

+ 64 - 0
src/api/device/list.ts

@@ -0,0 +1,64 @@
+import { defHttp } from '/@/utils/http/axios';
+import { PageParams, RentListGetResultModel, addCameraParams } from './model';
+
+enum Api {
+  pageList = '/zfb-api/zfb/camera/pageList',
+  addCamera = '/zfb-api/zfb/camera/add',
+  allCompany = '/zfb-api/zfb/company/listAll',
+  unbindDevice = '/zfb-api/zfb/company/unbindDevice',
+  editCamera = '/zfb-api/zfb/camera/update',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const ListApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.pageList,
+    params: params,
+    // data: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const unDeviceApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.unbindDevice,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const allCompanyApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.allCompany,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const addCameraApi = (params: addCameraParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.addCamera,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const editCameraApi = (params: addCameraParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.editCamera,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 70 - 0
src/api/device/model.ts

@@ -0,0 +1,70 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+
+export interface addCameraParams {
+  address: string;
+  balance: string;
+  cameraType: string;
+  childName: string;
+  companyId?: string;
+  orderSn?: string;
+  own: string;
+  snCode?: string;
+  wifiName: string;
+}
+export interface DeviceListItem {
+  id: number;
+  activatedTime: string;
+  address: string;
+  agentFrameworkId: string;
+  agentFrameworkName: string;
+  agentName: string;
+  balance: string;
+  cameraType: number;
+  childName: string;
+  companyId: string;
+  companyName: string;
+  cooperationUser: string;
+  cooperationUserName: string;
+  country: number;
+  createTime: string;
+  goodsId: number;
+  goodsName: string;
+  imageUrl: string;
+  inTime: string;
+  isExpire: string;
+  lastTime: string;
+  nickName: string;
+  orderSn: string;
+  outTime: string;
+  own: number;
+  pic: string;
+  recStatus: string;
+  responseUserIncrement: string;
+  sceneNum: string;
+  snCode: string;
+  space: string;
+  spaceContent: string;
+  spaceEndStr: string;
+  spaceEndTime: string;
+  spaceId: string;
+  spaceStr: string;
+  surplusDate: string;
+  totalSpace: number;
+  totalSpaceStr: string;
+  type: string;
+  usedSpace: number;
+  usedSpaceStr: string;
+  userId: string;
+  userIncrementId: string;
+  userName: string;
+  wifiName: string;
+}
+
+/**
+ * @description: Request list return value
+ */
+export type RentListGetResultModel = BasicFetchResult<DeviceListItem>;

src/api/demo/error.ts → src/api/error/index.ts


+ 20 - 0
src/api/feedback/list.ts

@@ -0,0 +1,20 @@
+import { defHttp } from '/@/utils/http/axios';
+import { PageParams, RentListGetResultModel } from './model';
+
+enum Api {
+  pageList = '/basic-api/feedback/list',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const ListApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.pageList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 20 - 0
src/api/feedback/model.ts

@@ -0,0 +1,20 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+
+export interface OrderListItem {
+  id: number;
+  name: string;
+  nickName: string;
+  phone: string;
+  feedbackType: number;
+  content: string;
+  createTime: string;
+}
+
+/**
+ * @description: Request list return value
+ */
+export type RentListGetResultModel = BasicFetchResult<OrderListItem>;

+ 20 - 0
src/api/member/list.ts

@@ -0,0 +1,20 @@
+import { defHttp } from '/@/utils/http/axios';
+import { PageParams, MemberListGetResultModel } from './model';
+
+enum Api {
+  pageList = '/basic-api/user/list',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const ListApi = (params: PageParams) =>
+  defHttp.post<MemberListGetResultModel>({
+    url: Api.pageList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 19 - 0
src/api/member/model.ts

@@ -0,0 +1,19 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+
+export interface MemberListItem {
+  id: number;
+  name: string;
+  image: string;
+  link: string;
+  createTime: string;
+  isShow: boolean;
+}
+
+/**
+ * @description: Request list return value
+ */
+export type MemberListGetResultModel = BasicFetchResult<MemberListItem>;

+ 1 - 22
src/api/model/baseModel.ts

@@ -13,7 +13,7 @@ export interface BasicFetchResult<T> {
   isFirstPage: boolean;
   isLastPage: boolean;
   lastPage: number;
-  list: any[];
+  list: T[];
   navigateFirstPage: number;
   navigateLastPage: number;
   navigatePages: number;
@@ -26,24 +26,3 @@ export interface BasicFetchResult<T> {
   size: number;
   startRow: number;
 }
-
-// endRow: 10
-// firstPage: 1
-// hasNextPage: true
-// hasPreviousPage: false
-// isFirstPage: true
-// isLastPage: false
-// lastPage: 8
-// list: []
-// navigateFirstPage: 1
-// navigateLastPage: 8
-// navigatePages: 8
-// navigatepageNums: [1, 2, 3, 4, 5, 6, 7, 8]
-// nextPage: 2
-// pageNum: 1
-// pageSize: 10
-// pages: 13
-// prePage: 0
-// size: 10
-// startRow: 1
-// total: 130

+ 90 - 0
src/api/order/list.ts

@@ -0,0 +1,90 @@
+import { defHttp } from '/@/utils/http/axios';
+import {
+  OrderInfoParams,
+  PageParams,
+  ListGetResultModel,
+  ExportExcelParams,
+  ExportExcelModel,
+} from './model';
+import type { Result } from '/#/axios';
+
+enum Api {
+  pageList = '/basic-api/order/list',
+  getOrderInfo = '/basic-api/order/info',
+  prderConfirm = '/basic-api/order/confirm',
+  shippingList = '/basic-api/shipping/list',
+  brandList = '/basic-api/brand/queryAll',
+  sendGoods = '/basic-api/order/sendGoods',
+  exportExcel = '/basic-api/order/export',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const ListApi = (params: PageParams) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.pageList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const ShippingListApi = (params: PageParams) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.shippingList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const sendGoods = (params) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.sendGoods,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const BrandListApi = (params: PageParams) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.brandList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const GetOrderInfoApi = (params: OrderInfoParams) =>
+  defHttp.get<ListGetResultModel>({
+    url: Api.getOrderInfo,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const exportExcelApi = (params: ExportExcelParams) =>
+  defHttp.post<ExportExcelModel>({
+    url: Api.exportExcel,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const confirmOrder = (params: OrderInfoParams) =>
+  defHttp.post<Result>({
+    url: Api.prderConfirm,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 30 - 0
src/api/order/model.ts

@@ -0,0 +1,30 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+
+export interface ExportExcelParams {
+  orderSnList: string;
+}
+export interface OrderInfoParams {
+  id: number;
+  brandId: number;
+}
+
+export interface OrderListItem {
+  id: number;
+  name: string;
+  image: string;
+  link: string;
+  createTime: string;
+  isShow: boolean;
+}
+
+export interface ExportExcelModel {
+  url: string;
+}
+/**
+ * @description: Request list return value
+ */
+export type ListGetResultModel = BasicFetchResult<OrderListItem>;

+ 111 - 0
src/api/product/category.ts

@@ -0,0 +1,111 @@
+import { defHttp } from '/@/utils/http/axios';
+import { PageParams, updateItem, RentListGetResultModel, addCategoryParams } from './model';
+import { Result, UploadFileParams } from '/#/axios';
+
+enum Api {
+  category = '/basic-api/category/queryAll',
+  attribute = '/basic-api/specification/list',
+  delete = '/basic-api/specification/delete',
+  update = '/basic-api/specification/update',
+  save = '/basic-api/specification/save',
+  uploadBanner = '/basic-api/sys/oss/upload',
+  addCategory = '/basic-api/category/save',
+  updateCategory = '/basic-api/category/update',
+  deleteCategory = '/basic-api/category/delete',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const categoryApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.category,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const attributeListApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.attribute,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const updateItemApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.update,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const saveItemApi = (params: updateItem) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.save,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const attributeDeleteApi = (params: string) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.delete,
+    params: [params],
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export function uploadBannerApi(
+  params: UploadFileParams,
+  // onUploadProgress: (progressEvent: ProgressEvent) => void,
+) {
+  return defHttp.uploadFile<Result>(
+    {
+      url: Api.uploadBanner,
+      // onUploadProgress,
+    },
+    params,
+  );
+}
+export const addCategoryApi = (params: addCategoryParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.addCategory,
+    params: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const updateCategoryApi = (params: addCategoryParams) =>
+  defHttp.post<Result>({
+    url: Api.updateCategory,
+    params: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const deleteCategoryApi = (params: string[]) =>
+  defHttp.post<Result>({
+    url: Api.deleteCategory,
+    params: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 93 - 0
src/api/product/list.ts

@@ -0,0 +1,93 @@
+import { defHttp } from '/@/utils/http/axios';
+import { PageParams, RentListGetResultModel } from './model';
+import { Result } from '/#/axios';
+
+enum Api {
+  pageList = '/basic-api/goods/list',
+  ref = '/basic-api/specification/list',
+  unSale = '/basic-api/goods/unSale',
+  enSale = '/basic-api/goods/enSale',
+  delete = '/basic-api/goods/delete',
+  info = '/basic-api/goods/info/',
+  update = '/basic-api/goods/update',
+  save = '/basic-api/goods/save',
+  queryAll = '/basic-api/specification/queryAll',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const queryAll = (params?: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.queryAll,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const ListApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.pageList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const InfoApi = (params: string) =>
+  defHttp.post<any>({
+    url: Api.info + params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const UnSaleApi = (params: string[]) =>
+  defHttp.post<Result>({
+    url: Api.unSale,
+    data: params.join(','),
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const SaveSaleApi = (params: any) =>
+  defHttp.post<Result>({
+    url: Api.save,
+    data: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const UpdateSaleApi = (params: any) =>
+  defHttp.post<Result>({
+    url: Api.update,
+    data: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const EnSaleApi = (params: string[]) =>
+  defHttp.post<Result>({
+    url: Api.enSale,
+    data: params.join(','),
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const DeleteApi = (params: string[]) =>
+  defHttp.post<Result>({
+    url: Api.delete,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 43 - 0
src/api/product/model.ts

@@ -0,0 +1,43 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+
+export interface addCategoryParams {
+  id?: number;
+  isShow: string;
+  level: 'L1' | 'L2';
+  name: string;
+  type?: number;
+  parentId?: string;
+  wapBannerUrl?: string;
+  sortOrder?: number;
+  show?: number;
+}
+export interface OrderListItem {
+  id: number;
+  limit: number | null;
+  page: number | null;
+  name: string;
+  image: string;
+  link: string;
+  createTime: string;
+  isShow: boolean;
+}
+
+export interface OrderListItem {
+  limit: number | null;
+  page: number | null;
+  name: string;
+}
+
+export interface updateItem {
+  id: number | null;
+  name: string;
+}
+
+/**
+ * @description: Request list return value
+ */
+export type RentListGetResultModel = BasicFetchResult<OrderListItem>;

+ 81 - 0
src/api/scene/list.ts

@@ -0,0 +1,81 @@
+import { defHttp } from '/@/utils/http/axios';
+import {
+  PageParams,
+  RentListGetResultModel,
+  SceneEditParam,
+  SceneDownloadParam,
+  GetDownloadProcessModel,
+  UpdateParams,
+} from './model';
+import { Result } from '/#/axios';
+
+enum Api {
+  pageList = '/zfb-api/zfb/scene/pageList',
+  generateSceneEditToken = '/zfb-api/zfb/api/platform/generateSceneEditToken',
+  downloadSceneData = '/zfb-api/zfb/scene/downloadSceneData',
+  getDownloadProcess = '/zfb-api/zfb/scene/getDownloadProcess',
+  update = '/zfb-api/zfb/scene/update',
+  generateDefaultLiveRoom = '/basic-api/scene/generateDefaultLiveRoom',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const UpdateApi = (params: UpdateParams) =>
+  defHttp.post<Result>({
+    url: Api.update,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const ListApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.pageList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const downloadSceneDataAPi = (params: SceneDownloadParam) =>
+  defHttp.get<Result>({
+    url: Api.downloadSceneData,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const getDownloadProcessApi = (params: SceneDownloadParam) =>
+  defHttp.get<GetDownloadProcessModel>({
+    url: Api.getDownloadProcess,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const generateSceneEditTokenApi = (params: SceneEditParam) =>
+  defHttp.post<Result>({
+    url: Api.generateSceneEditToken,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const generateDefaultLiveRoomApi = (params: SceneDownloadParam) =>
+  defHttp.post<Result>({
+    url: Api.generateDefaultLiveRoom,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 165 - 0
src/api/scene/live.ts

@@ -0,0 +1,165 @@
+import { defHttp } from '/@/utils/http/axios';
+import {
+  PageParams,
+  InfoParams,
+  RentListGetResultModel,
+  SceneLiveItem,
+  bindAnchorListParam,
+  GetAllSceneModel,
+  // SceneLiveModel,
+} from './model';
+import { Result, UploadFileParams } from '/#/axios';
+enum Api {
+  pageList = '/basic-api/brand/brandBindList',
+  bindAnchorList = '/zfb-api/zfb/shop/sys/user/bindList',
+  olderBindAnchorList = '/basic-api/sys/user/bindList',
+  // brandTypeList = '/zfb-api/zfb/shop/brand/brandTypeList',
+  brandTypeList = '/basic-api/brand/brandTypeList',
+  // bindUser = '/zfb-api/zfb/shop/sys/brand/bindUser',
+  bindUser = '/basic-api/brand/bindUser',
+  brandUpdate = '/basic-api/brand/update',
+  brandDelete = '/basic-api/brand/delete',
+  upload = '/basic-api/sys/oss/upload',
+  uploadVideo = '/basic-api/sys/oss/upLoadVideo',
+  getAllScene = '/zfb-api/zfb/scene/list',
+  getBrandInfo = '/basic-api/brand/info',
+  addSave = '/basic-api/brand/save',
+}
+export type SceneLiveItemResult = SceneLiveItem;
+/**
+ * @description: Get sample list value
+ */
+
+export const ListApi = (params: PageParams) =>
+  defHttp.get<RentListGetResultModel>({
+    url: Api.pageList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const bindOldAnchorListApi = (params: bindAnchorListParam) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.olderBindAnchorList,
+    params: params,
+    data: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const bindAnchorListApi = (params: bindAnchorListParam) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.bindAnchorList,
+    params: params,
+    data: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const bindUserApi = (params: any) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.bindUser,
+    params: params,
+    // data: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const brandTypeListApi = (params: PageParams) =>
+  defHttp.get<RentListGetResultModel>({
+    url: Api.brandTypeList,
+
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export function uploadLiveApi(
+  params: UploadFileParams,
+  // onUploadProgress: (progressEvent: ProgressEvent) => void,
+) {
+  return defHttp.uploadFile<Result>(
+    {
+      url: Api.upload,
+      // onUploadProgress,
+    },
+    params,
+  );
+}
+export function uploadLiveVideoApi(
+  params: UploadFileParams,
+  // onUploadProgress: (progressEvent: ProgressEvent) => void,
+) {
+  return defHttp.uploadFile<Result>(
+    {
+      url: Api.uploadVideo,
+      // onUploadProgress,
+    },
+    params,
+  );
+}
+
+export const getAllSceneApi = (params: PageParams) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.getAllScene,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const getLiveInfoApi = (params: InfoParams) => {
+  return defHttp.post<SceneLiveItem>({
+    url: Api.getBrandInfo,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+};
+export const brandUpdateApi = (params: SceneLiveItem) =>
+  defHttp.post<GetAllSceneModel>({
+    url: Api.brandUpdate,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const LiveSceneAddApi = (params: SceneLiveItem) =>
+  defHttp.post<GetAllSceneModel>({
+    url: Api.brandDelete,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const LiveSceneDeleteApi = (params: string[]) =>
+  defHttp.post<GetAllSceneModel>({
+    url: Api.brandDelete,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const addSave = (params: SceneLiveItem) =>
+  defHttp.post<RentListGetResultModel>({
+    url: Api.addSave,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 95 - 0
src/api/scene/model.ts

@@ -0,0 +1,95 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+export interface bindAnchorListParam {
+  brandId?: number | string;
+  canShow?: number;
+  type?: number;
+  userId?: number | string;
+}
+export interface InfoParams {
+  id?: number | string;
+  token?: string;
+}
+export interface UpdateParams {
+  sceneNum?: string;
+  isShow?: string;
+  appListPicUrl?: string;
+}
+
+export interface SceneDownloadParam {
+  sceneNum?: string;
+}
+export interface SceneEditParam {
+  sceneNum: string;
+  userName: string;
+}
+
+export interface SceneLiveItem {
+  address: string;
+  adminId: number;
+  appListPicUrl: string;
+  bindShowerId: number;
+  bindShowerName: string;
+  bindShowerNameList: string;
+  city: string;
+  contractPhone: string;
+  createTime: number;
+  createUserDeptId: number;
+  createUserId: number;
+  deleted: number;
+  id: number;
+  introduceVideo: string;
+  introduceVideoCover: string;
+  latitude: number;
+  liveRoomUrl: string;
+  livestreamStatus: number;
+  longitude: number;
+  name: string;
+  picList: string;
+  sceneName: string;
+  sceneNum: string;
+  sceneUrl: string;
+  shareWxQrCode: string;
+  simpleDesc: string;
+  sortOrder: number;
+  token: string;
+  type: number;
+  updateTime: number;
+  updateUserId: number;
+}
+
+export interface SceneProccessItem {
+  precent?: number;
+  status?: number;
+  url?: string;
+}
+
+export interface sceneItem {
+  appListPicUrl: string;
+  createTime: number;
+  createUserId: number;
+  deleted: number;
+  id: number;
+  isShow: number;
+  name: string;
+  sceneNum: string;
+  sceneUrl: string;
+  token: string;
+  updateTime: number;
+  updateUserId: number;
+}
+
+export interface SceneLiveModel {
+  brand: SceneLiveItem;
+  code?: number;
+}
+/**
+ * @description: Request list return value
+ */
+export type RentListGetResultModel = BasicFetchResult<SceneLiveItem>;
+export type LiveListGetResultModel = BasicFetchResult<SceneLiveItem>;
+export type GetDownloadProcessModel = BasicFetchResult<SceneProccessItem>;
+export type GetAllSceneModel = BasicFetchResult<sceneItem>;

+ 105 - 0
src/api/staff/list.ts

@@ -0,0 +1,105 @@
+import { defHttp } from '/@/utils/http/axios';
+import { PageParams, ListGetResultModel, DelParams, roleParams } from './model';
+import { Result } from '/#/axios';
+
+enum Api {
+  pageList = '/zfb-api/zfb/shop/sys/user/staffList',
+  preDel = '/zfb-api/zfb/shop/sys/user/preDeleteStaff',
+  roleList = '/zfb-api/zfb/shop/sys/user/roleList',
+  getRoleListByParam = '/zfb-api/zfb/shop/sys/user/getRoleListByParam',
+  staffSave = '/zfb-api/zfb/shop/sys/user/staffSave',
+  update = '/zfb-api/zfb/shop/sys/user/update',
+  checkUser = '/zfb-api/zfb/user/checkUserExists',
+  deleteStaff = '/zfb-api/zfb/shop/sys/user/deleteStaff',
+  getNumByStaff = '/zfb-api/zfb/shop/sys/user/getNumByStaff',
+}
+
+/**
+ * @description: Get sample list value
+ */
+
+export const ListApi = (params: PageParams) =>
+  defHttp.post<ListGetResultModel>({
+    url: Api.pageList,
+    params,
+    data: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const getNumByStaff = (params: any) =>
+  defHttp.get<Result>({
+    url: Api.getNumByStaff,
+    params,
+    data: params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const delApi = (params: DelParams) =>
+  defHttp.post<Result>({
+    url: Api.deleteStaff,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const preDelApi = (params: number) =>
+  defHttp.post<Result>({
+    url: Api.preDel,
+    params: { userId: params },
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const getRoleListByParam = (params: roleParams) =>
+  defHttp.post<Result>({
+    url: Api.getRoleListByParam,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const roleLIstApi = (params) =>
+  defHttp.post<Result>({
+    url: Api.roleList,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const checkUserApi = (params) =>
+  defHttp.post<boolean>({
+    url: Api.checkUser,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+
+export const saveApi = (params) =>
+  defHttp.post<Result>({
+    url: Api.staffSave,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });
+export const updateApi = (params) =>
+  defHttp.post<Result>({
+    url: Api.update,
+    params,
+    headers: {
+      // @ts-ignore
+      ignoreCancelToken: true,
+    },
+  });

+ 30 - 0
src/api/staff/model.ts

@@ -0,0 +1,30 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+/**
+ * @description: Request list interface parameters
+ */
+export type PageParams = BasicPageParams;
+
+export interface DelParams {
+  userId: number;
+  toUserId: number;
+  toUserPhone: string;
+}
+
+export interface roleParams {
+  type: number;
+  roleId: number;
+}
+export interface StaffListItem {
+  id: number;
+
+  name: string;
+  company: string;
+  phone: string;
+  status: string;
+  role: string;
+  createTime: string;
+}
+/**
+ * @description: Request list return value
+ */
+export type ListGetResultModel = BasicFetchResult<StaffListItem>;

+ 2 - 2
src/api/sys/menu.ts

@@ -2,7 +2,7 @@ import { defHttp } from '/@/utils/http/axios';
 import { getMenuListResultModel } from './model/menuModel';
 
 enum Api {
-  GetMenuList = '/getMenuList',
+  GetMenuList = '/zfb-api/zfb/shop/sys/menu/user',
 }
 
 /**
@@ -10,5 +10,5 @@ enum Api {
  */
 
 export const getMenuList = () => {
-  return defHttp.get<getMenuListResultModel>({ url: Api.GetMenuList });
+  return defHttp.post<getMenuListResultModel>({ url: Api.GetMenuList });
 };

+ 51 - 17
src/api/sys/model/userModel.ts

@@ -1,38 +1,72 @@
+import type { UserInfo } from '/#/store';
 /**
  * @description: Login interface parameters
  */
 export interface LoginParams {
-  username: string;
-  password: string;
+  userName: string;
+  userPassword: string;
+  captcha: string;
 }
 
 export interface RoleInfo {
+  userID?: string;
   roleName: string;
   value: string;
+  brandList: string[] | any;
+  canShow: string;
+  createTime: number;
+  createUserId: number;
+  deptExpirationDate: number;
+  deptId: number;
+  deptManagerPhoneNum: string;
+  deptName: string;
+  email: string;
+  fdkkPassword: string;
+  fdkkUser: string;
+  isPlatformStreamer: false;
+  mobile: string;
+  parentDeptId: number;
+  parentDeptName: number;
+  password: string;
+  roleId: number;
+  roleIdList: any[];
+  roleList: number;
+  status: number;
+  userId: number;
+  username: string;
 }
 
 /**
  * @description: Login interface return value
  */
 export interface LoginResultModel {
-  userId: string | number;
+  id?: string | number;
   token: string;
-  role: RoleInfo;
+  role?: RoleInfo;
+  user: RoleInfo;
 }
+export type GetUserInfoModel = UserInfo;
 
+export interface updateUserInfoPasswordParam {
+  id: string | number;
+  password?: string;
+  newPassword?: string;
+}
 /**
  * @description: Get user information return value
  */
-export interface GetUserInfoModel {
-  roles: RoleInfo[];
-  // 用户id
-  userId: string | number;
-  // 用户名
-  username: string;
-  // 真实名字
-  realName: string;
-  // 头像
-  avatar: string;
-  // 介绍
-  desc?: string;
-}
+// export interface GetUserInfoModel {
+//   roles: RoleInfo[];
+//   // 用户id
+//   id: string | number;
+
+//   // userId: string | number;
+//   // 用户名
+//   userName: string;
+//   // 真实名字
+//   realName: string;
+//   // 头像
+//   avatar: string;
+//   // 介绍
+//   desc?: string;
+// }

+ 39 - 7
src/api/sys/user.ts

@@ -1,12 +1,22 @@
 import { defHttp } from '/@/utils/http/axios';
-import { LoginParams, LoginResultModel, GetUserInfoModel } from './model/userModel';
-
+import {
+  LoginParams,
+  LoginResultModel,
+  GetUserInfoModel,
+  updateUserInfoPasswordParam,
+} from './model/userModel';
+import { encodeStr } from '/@/utils/encodeUtil';
 import { ErrorMessageMode } from '/#/axios';
+import { ContentTypeEnum } from '/@/enums/httpEnum';
+
+// import { encode } from 'js-base64';
 
 enum Api {
-  Login = '/login',
+  // Login = '/basic-api/sys/login',
+  Login = '/zfb-api/zfb/loginBackground',
   Logout = '/logout',
-  GetUserInfo = '/getUserInfo',
+  updatePassword = '/zfb-api/zfb/user/updatePassword',
+  GetUserInfo = '/zfb-api/zfb/shop/sys/user/infoAnon',
   GetPermCode = '/getPermCode',
 }
 
@@ -14,10 +24,23 @@ enum Api {
  * @description: user login api
  */
 export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal') {
+  // const form = new FormData();
+  // const encryptPassword: string = encodeStr(window.btoa(params.password));
+  // form.append('username', params.username);
+  // form.append('password', encryptPassword);
+  // form.append('captcha', params.captcha);
+
+  const paramData: LoginParams = {
+    ...params,
+    userPassword: encodeStr(window.btoa(params.userPassword)),
+  };
+
   return defHttp.post<LoginResultModel>(
     {
       url: Api.Login,
-      params,
+      // params,
+      params: paramData,
+      headers: { 'Content-Type': ContentTypeEnum.JSON },
     },
     {
       errorMessageMode: mode,
@@ -28,8 +51,11 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
 /**
  * @description: getUserInfo
  */
-export function getUserInfo() {
-  return defHttp.get<GetUserInfoModel>({ url: Api.GetUserInfo }, { errorMessageMode: 'none' });
+export function getUserInfo(id: number) {
+  return defHttp.post<GetUserInfoModel>(
+    { url: `${Api.GetUserInfo}/${id}` },
+    { errorMessageMode: 'none' },
+  );
 }
 
 export function getPermCode() {
@@ -39,3 +65,9 @@ export function getPermCode() {
 export function doLogout() {
   return defHttp.get({ url: Api.Logout });
 }
+export function updatePasswordApi(params: updateUserInfoPasswordParam) {
+  return defHttp.post<GetUserInfoModel>(
+    { url: Api.updatePassword, params },
+    // { errorMessageMode: 'none' },
+  );
+}

+ 12 - 0
src/api/system/error.ts

@@ -0,0 +1,12 @@
+import { defHttp } from '/@/utils/http/axios';
+
+enum Api {
+  // The address does not exist
+  Error = '/error',
+}
+
+/**
+ * @description: Trigger ajax error
+ */
+
+export const fireErrorApi = () => defHttp.get({ url: Api.Error });

+ 7 - 0
src/api/system/model/accountModel.ts

@@ -0,0 +1,7 @@
+export interface GetAccountInfoModel {
+  email: string;
+  name: string;
+  introduction: string;
+  phone: string;
+  address: string;
+}

+ 12 - 0
src/api/system/model/areaModel.ts

@@ -0,0 +1,12 @@
+export interface AreaModel {
+  id: string;
+  code: string;
+  parentCode: string;
+  name: string;
+  levelType: number;
+  [key: string]: string | number;
+}
+
+export interface AreaParams {
+  parentCode: string;
+}

+ 15 - 0
src/api/system/model/optionsModel.ts

@@ -0,0 +1,15 @@
+import { BasicFetchResult } from '/@/api/model/baseModel';
+
+export interface DemoOptionsItem {
+  label: string;
+  value: string;
+}
+
+export interface selectParams {
+  id: number | string;
+}
+
+/**
+ * @description: Request list return value
+ */
+export type DemoOptionsGetResultModel = BasicFetchResult<DemoOptionsItem>;

+ 100 - 0
src/api/system/model/systemModel.ts

@@ -0,0 +1,100 @@
+import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
+
+export type AccountParams = BasicPageParams & {
+  account?: string;
+  nickname?: string;
+};
+export type DelAccountParams = {
+  userId: string;
+};
+
+export type RoleParams = {
+  roleName?: string;
+  status?: string;
+};
+
+export type SaveRoleParams = {
+  deptId: string;
+  deptIdList: (number | string)[];
+  deptName: string;
+  menuIdList: number[];
+  roleName: string;
+};
+
+export type RolePageParams = BasicPageParams & RoleParams;
+
+export type CheckUserParams = {
+  phone?: string;
+};
+
+export type DeptParams = {
+  deptName?: string;
+  status?: string;
+};
+
+export type MenuParams = {
+  icon: string;
+  name: string;
+  orderNum: number;
+  parentId: number;
+  parentName: string;
+  perms: string;
+  status: number;
+  type: number;
+  url: string;
+};
+
+export interface AccountListItem {
+  id: string;
+  account: string;
+  email: string;
+  nickname: string;
+  role: number;
+  createTime: string;
+  remark: string;
+  status: number;
+}
+
+export interface DeptListItem {
+  id: string;
+  orderNo: string;
+  createTime: string;
+  remark: string;
+  status: number;
+}
+
+export interface MenuListItem {
+  menuId: string;
+  children?: MenuListItem[];
+  icon: string;
+  name: string;
+  orderNum: number;
+  parentId: number;
+  parentName: string;
+  perms: string;
+  status: number;
+  type: number;
+  url: string;
+}
+
+export interface RoleListItem {
+  id: string;
+  roleName: string;
+  roleValue: string;
+  status: number;
+  orderNo: string;
+  createTime: string;
+}
+
+/**
+ * @description: Request list return value
+ */
+export type AccountListGetResultModel = BasicFetchResult<AccountListItem>;
+
+export type DeptListGetResultModel = BasicFetchResult<DeptListItem>;
+
+export type MenuListGetResultModel = BasicFetchResult<MenuListItem>;
+
+export type RolePageListGetResultModel = BasicFetchResult<RoleListItem>;
+
+export type RoleListGetResultModel = RoleListItem[];

+ 111 - 0
src/api/system/system.ts

@@ -0,0 +1,111 @@
+import {
+  AccountParams,
+  DelAccountParams,
+  DeptListItem,
+  MenuParams,
+  RoleParams,
+  RolePageParams,
+  CheckUserParams,
+  MenuListGetResultModel,
+  DeptListGetResultModel,
+  AccountListGetResultModel,
+  RolePageListGetResultModel,
+  RoleListGetResultModel,
+  SaveRoleParams,
+} from './model/systemModel';
+import { Result } from '/#/axios';
+import { defHttp } from '/@/utils/http/axios';
+// import { ContentTypeEnum } from '/@/enums/httpEnum';
+// sys/user/list
+// /sys/role/list
+// sys/menu/queryAll
+// sys/menu/update
+enum Api {
+  MenuList = '/zfb-api/zfb/shop/sys/menu/queryAll',
+  saveMenu = '/zfb-api/zfb/shop/sys/menu/save',
+  updateMenu = '/zfb-api/zfb/shop/sys/menu/update',
+  deleteMenu = '/zfb-api/zfb/shop/sys/menu/delete',
+  MenuUser = '/zfb-api/zfb/shop/sys/menu/delete',
+
+  AccountList = '/zfb-api/zfb/shop/sys/user/list',
+  saveAccount = '/zfb-api/zfb/shop/sys/user/save',
+  updateAccount = '/zfb-api/zfb/shop/sys/user/update',
+  IsAccountExist = '/basic-api/system/accountExist',
+  deleteAccountUser = '/zfb-api/zfb/shop/sys/user/preDeleteStaff',
+
+  RolePageList = '/zfb-api/zfb/shop/sys/role/list',
+  setRoleStatus = '/basic-api/system/setRoleStatus',
+  saveRole = '/zfb-api/zfb/shop/sys/role/save',
+  deleteRole = '/zfb-api/zfb/shop/sys/role/delete',
+  updateRole = '/zfb-api/zfb/shop/sys/role/update',
+  GetAllRoleList = '/basic-api/system/getAllRoleList',
+  roleSelectList = '/zfb-api/zfb/shop/sys/role/select',
+
+  DeptList = '/zfb-api/zfb/shop/sys/dept/list',
+
+  checkUser = '/zfb-api/zfb/user/checkUserExists',
+}
+
+export const getAccountList = (params: AccountParams) =>
+  defHttp.post<AccountListGetResultModel>({ url: Api.AccountList, params });
+
+export const deleteAccountUserApi = (params: DelAccountParams) =>
+  defHttp.post<AccountListGetResultModel>({ url: Api.deleteAccountUser, params });
+
+export const saveAccountUserApi = (params: AccountParams) =>
+  defHttp.post<AccountListGetResultModel>({ url: Api.saveAccount, params });
+
+export const updateAccountUserApi = (params: AccountParams) =>
+  defHttp.post<AccountListGetResultModel>({ url: Api.updateAccount, params });
+
+//decpored
+
+export const getDeptList = (params?: DeptListItem) =>
+  defHttp.get<DeptListGetResultModel>({ url: Api.DeptList, params });
+
+export const getMenuList = (params?: MenuParams) =>
+  defHttp.post<MenuListGetResultModel>({
+    url: Api.MenuList,
+    params: params,
+  });
+//menu
+export const saveMenuApi = (params?: MenuParams) =>
+  defHttp.post<MenuListGetResultModel>({ url: Api.saveMenu, params });
+
+export const updateMenuApi = (params?: MenuParams) =>
+  defHttp.post<MenuListGetResultModel>({ url: Api.updateMenu, params });
+
+export const deleteMenuApi = (params?: (string | number)[]) =>
+  defHttp.post<MenuListGetResultModel>({ url: Api.deleteMenu, params });
+
+//roles
+export const getRoleListByPage = (params?: RolePageParams) =>
+  defHttp.post<RolePageListGetResultModel>({ url: Api.RolePageList, params });
+
+export const getAllRoleList = (params?: RoleParams) =>
+  defHttp.post<RoleListGetResultModel>({ url: Api.GetAllRoleList, params });
+
+export const roleSelectListApi = (params?: RoleParams) =>
+  defHttp.post<RoleListGetResultModel>({ url: Api.roleSelectList, params });
+
+export const setRoleStatus = (id: number, status: string) =>
+  defHttp.post({ url: Api.setRoleStatus, params: { id, status } });
+
+export const saveRoleApi = (params: SaveRoleParams) =>
+  //TODO 临时加deptId调试
+  defHttp.post({ url: Api.saveRole, params: params });
+//TODO 临时d加eptId调试
+export const updateRoleApi = (params: SaveRoleParams) =>
+  defHttp.post({ url: Api.updateRole, params: params });
+
+export const deleteRoleApi = (params: (string | number)[]) =>
+  defHttp.post({ url: Api.deleteRole, params: params });
+
+export const isAccountExist = (account: string) =>
+  defHttp.post({ url: Api.IsAccountExist, params: { account } }, { errorMessageMode: 'none' });
+
+export const deptListApi = (params?: RolePageParams) =>
+  defHttp.post<RolePageListGetResultModel>({ url: Api.DeptList, params });
+
+export const checkUserApi = (params?: CheckUserParams) =>
+  defHttp.post<Result>({ url: Api.checkUser, params });

BIN
src/assets/images/header.jpg


BIN
src/assets/images/logo.png


+ 81 - 86
src/components/CardList/src/CardList.vue

@@ -1,3 +1,81 @@
+<template>
+  <div class="p-2">
+    <div class="p-4 mb-2 bg-white">
+      <BasicForm @register="registerForm" />
+    </div>
+    {{ sliderProp.width }}
+    <div class="p-2 bg-white">
+      <List
+        :grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
+        :data-source="data"
+        :pagination="paginationProp"
+      >
+        <template #header>
+          <div class="flex justify-end space-x-2"
+            ><slot name="header"></slot>
+            <Tooltip>
+              <template #title>
+                <div class="w-50">每行显示数量</div
+                ><Slider
+                  id="slider"
+                  v-bind="sliderProp"
+                  v-model:value="grid"
+                  @change="sliderChange"
+              /></template>
+              <Button><TableOutlined /></Button>
+            </Tooltip>
+            <Tooltip @click="fetch">
+              <template #title>刷新</template>
+              <Button><RedoOutlined /></Button>
+            </Tooltip>
+          </div>
+        </template>
+        <template #renderItem="{ item }">
+          <ListItem>
+            <Card>
+              <template #title></template>
+              <template #cover>
+                <div :class="height">
+                  <Image :src="item.imgs[0]" />
+                </div>
+              </template>
+              <template class="ant-card-actions" #actions>
+                <!--              <SettingOutlined key="setting" />-->
+                <EditOutlined key="edit" />
+                <Dropdown
+                  :trigger="['hover']"
+                  :dropMenuList="[
+                    {
+                      text: '删除',
+                      event: '1',
+                      popConfirm: {
+                        title: '是否确认删除',
+                        confirm: handleDelete.bind(null, item.id),
+                      },
+                    },
+                  ]"
+                  popconfirm
+                >
+                  <EllipsisOutlined key="ellipsis" />
+                </Dropdown>
+              </template>
+
+              <CardMeta>
+                <template #title>
+                  <TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
+                </template>
+                <template #avatar>
+                  <Avatar :src="item.avatar" />
+                </template>
+                <template #description>{{ item.time }}</template>
+              </CardMeta>
+            </Card>
+          </ListItem>
+        </template>
+      </List>
+    </div>
+  </div>
+</template>
 <script lang="ts" setup>
   import { computed, onMounted, ref } from 'vue';
   import {
@@ -9,6 +87,7 @@
   import { List, Card, Image, Typography, Tooltip, Slider, Avatar } from 'ant-design-vue';
   import { Dropdown } from '/@/components/Dropdown';
   import { BasicForm, useForm } from '/@/components/Form';
+  import { propTypes } from '/@/utils/propTypes';
   import { Button } from '/@/components/Button';
   import { isFunction } from '/@/utils/is';
   import { useSlider, grid } from './data';
@@ -20,15 +99,9 @@
   // 组件接收参数
   const props = defineProps({
     // 请求API的参数
-    params: {
-      type: Object,
-      default: () => ({}),
-    },
+    params: propTypes.object.def({}),
     //api
-    api: {
-      type: Function,
-      default: null,
-    },
+    api: propTypes.func,
   });
   //暴露内部方法
   const emit = defineEmits(['getMethod', 'delete']);
@@ -103,81 +176,3 @@
     emit('delete', id);
   }
 </script>
-
-<template>
-  <div class="p-2">
-    <div class="p-4 mb-2 bg-white">
-      <BasicForm @register="registerForm" />
-    </div>
-    {{ sliderProp.width }}
-    <div class="p-2 bg-white">
-      <List
-        :grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
-        :data-source="data"
-        :pagination="paginationProp"
-      >
-        <template #header>
-          <div class="flex justify-end space-x-2"
-            ><slot name="header"></slot>
-            <Tooltip>
-              <template #title>
-                <div class="w-50">每行显示数量</div
-                ><Slider
-                  id="slider"
-                  v-bind="sliderProp"
-                  v-model:value="grid"
-                  @change="sliderChange"
-              /></template>
-              <Button><TableOutlined /></Button>
-            </Tooltip>
-            <Tooltip @click="fetch">
-              <template #title>刷新</template>
-              <Button><RedoOutlined /></Button>
-            </Tooltip>
-          </div>
-        </template>
-        <template #renderItem="{ item }">
-          <ListItem>
-            <Card>
-              <template #title></template>
-              <template #cover>
-                <div :class="height">
-                  <Image :src="item.imgs[0]" />
-                </div>
-              </template>
-              <template #actions>
-                <EditOutlined key="edit" />
-                <Dropdown
-                  :trigger="['hover']"
-                  :dropMenuList="[
-                    {
-                      text: '删除',
-                      event: '1',
-                      popConfirm: {
-                        title: '是否确认删除',
-                        confirm: handleDelete.bind(null, item.id),
-                      },
-                    },
-                  ]"
-                  popconfirm
-                >
-                  <EllipsisOutlined key="ellipsis" />
-                </Dropdown>
-              </template>
-
-              <CardMeta>
-                <template #title>
-                  <TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
-                </template>
-                <template #avatar>
-                  <Avatar :src="item.avatar" />
-                </template>
-                <template #description>{{ item.time }}</template>
-              </CardMeta>
-            </Card>
-          </ListItem>
-        </template>
-      </List>
-    </div>
-  </div>
-</template>

+ 1 - 1
src/components/CardList/src/data.ts

@@ -1,5 +1,5 @@
 import { ref } from 'vue';
-//每行个数
+// 每行个数
 export const grid = ref(12);
 // slider属性
 export const useSlider = (min = 6, max = 12) => {

+ 2 - 2
src/components/CodeEditor/src/codemirror/codemirror.css

@@ -53,7 +53,7 @@
   color: var(--comment);
   text-align: right;
   white-space: nowrap;
-  opacity: 60%;
+  opacity: 0.6;
 }
 
 .CodeMirror-guttermarker {
@@ -90,7 +90,7 @@
   display: inline-block;
   font-size: 0.8em;
   content: '>';
-  opacity: 80%;
+  opacity: 0.8;
   transform: rotate(90deg);
   transition: transform 0.2s;
 }

+ 1 - 1
src/components/Container/src/collapse/CollapseContainer.vue

@@ -1,6 +1,6 @@
 <template>
   <div :class="prefixCls">
-    <CollapseHeader v-bind="$props" :prefixCls="prefixCls" :show="show" @expand="handleExpand">
+    <CollapseHeader v-bind="props" :prefixCls="prefixCls" :show="show" @expand="handleExpand">
       <template #title>
         <slot name="title"></slot>
       </template>

+ 9 - 9
src/components/ContextMenu/src/ContextMenu.vue

@@ -60,6 +60,7 @@
         const top = body.clientHeight < y + menuHeight ? y - menuHeight : y;
         return {
           ...styles,
+          position: 'absolute',
           width: `${width}px`,
           left: `${left + 1}px`,
           top: `${top + 1}px`,
@@ -124,15 +125,11 @@
         }
         const { items } = props;
         return (
-          <Menu
-            inlineIndent={12}
-            mode="vertical"
-            class={prefixCls}
-            ref={wrapRef}
-            style={unref(getStyle)}
-          >
-            {renderMenuItem(items)}
-          </Menu>
+          <div class={prefixCls}>
+            <Menu inlineIndent={12} mode="vertical" ref={wrapRef} style={unref(getStyle)}>
+              {renderMenuItem(items)}
+            </Menu>
+          </div>
         );
       };
     },
@@ -185,6 +182,9 @@
     background-clip: padding-box;
     user-select: none;
 
+    &__item {
+      margin: 0 !important;
+    }
     .item-style();
 
     .ant-divider {

+ 37 - 4
src/components/Cropper/src/CopperModal.vue

@@ -2,7 +2,7 @@
   <BasicModal
     v-bind="$attrs"
     @register="register"
-    :title="t('component.cropper.modalTitle')"
+    :title="title || t('component.cropper.modalTitle')"
     width="800px"
     :canFullscreen="false"
     @ok="handleOk"
@@ -15,6 +15,7 @@
             v-if="src"
             :src="src"
             height="300px"
+            :aspectRatio="aspectRatio"
             :circled="circled"
             @cropend="handleCropend"
             @ready="handleReady"
@@ -22,7 +23,7 @@
         </div>
 
         <div :class="`${prefixCls}-toolbar`">
-          <Upload :fileList="[]" accept="image/*" :beforeUpload="handleBeforeUpload">
+          <Upload :fileList="[]" accept=".jpg,.jpeg.gif,.png" :beforeUpload="handleBeforeUpload">
             <Tooltip :title="t('component.cropper.selectImage')" placement="bottom">
               <a-button size="small" preIcon="ant-design:upload-outlined" type="primary" />
             </Tooltip>
@@ -113,7 +114,7 @@
 <script lang="ts">
   import type { CropendResult, Cropper } from './typing';
 
-  import { defineComponent, ref } from 'vue';
+  import { defineComponent, ref, watchEffect } from 'vue';
   import CropperImage from './Cropper.vue';
   import { Space, Upload, Avatar, Tooltip } from 'ant-design-vue';
   import { useDesign } from '/@/hooks/web/useDesign';
@@ -121,14 +122,19 @@
   import { dataURLtoBlob } from '/@/utils/file/base64Conver';
   import { isFunction } from '/@/utils/is';
   import { useI18n } from '/@/hooks/web/useI18n';
+  import { useMessage } from '/@/hooks/web/useMessage';
 
   type apiFunParams = { file: Blob; name: string; filename: string };
 
   const props = {
-    circled: { type: Boolean, default: true },
+    circled: { type: Boolean, default: false },
+    src: { type: String, default: '' },
+    title: { type: String },
+    maxSize: { type: Number, default: 5 },
     uploadApi: {
       type: Function as PropType<(params: apiFunParams) => Promise<any>>,
     },
+    aspectRatio: { type: Number, default: 1 },
   };
 
   export default defineComponent({
@@ -140,6 +146,7 @@
       let filename = '';
       const src = ref('');
       const previewSource = ref('');
+      const { createMessage } = useMessage();
       const cropper = ref<Cropper>();
       let scaleX = 1;
       let scaleY = 1;
@@ -148,8 +155,29 @@
       const [register, { closeModal, setModalProps }] = useModalInner();
       const { t } = useI18n();
 
+      watchEffect(() => {
+        if (props.src) {
+          src.value = props.src;
+        }
+      });
+
       // Block upload
       function handleBeforeUpload(file: File) {
+        const accept = ['image/jpg', 'image/jpeg', 'image/gif', 'image/png'];
+        const isAccept = accept.find((i) => String(file.type) === i);
+        if (!isAccept) {
+          createMessage.error(t('component.upload.illegalFile'));
+          return false;
+        }
+        const { size } = file;
+        const { maxSize } = props;
+        if (maxSize && size / 1024 / 1024 >= maxSize) {
+          createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
+          return false;
+        }
+
+        console.log('file.type', isAccept, file.type);
+
         const reader = new FileReader();
         reader.readAsDataURL(file);
         src.value = '';
@@ -181,6 +209,11 @@
 
       async function handleOk() {
         const uploadApi = props.uploadApi;
+
+        if (!previewSource.value) {
+          createMessage.error(t('component.upload.empty'));
+          return;
+        }
         if (uploadApi && isFunction(uploadApi)) {
           const blob = dataURLtoBlob(previewSource.value);
           try {

+ 2 - 0
src/components/Cropper/src/Cropper.vue

@@ -47,6 +47,7 @@
     src: { type: String, required: true },
     alt: { type: String },
     circled: { type: Boolean, default: false },
+    aspectRatio: { type: Number, default: 1 },
     realTimePreview: { type: Boolean, default: true },
     height: { type: [String, Number], default: '360px' },
     crossorigin: {
@@ -104,6 +105,7 @@
         }
         cropper.value = new Cropper(imgEl, {
           ...defaultOptions,
+          aspectRatio: props.aspectRatio,
           ready: () => {
             isReady.value = true;
             realTimeCroppered();

+ 16 - 4
src/components/Cropper/src/CropperAvatar.vue

@@ -10,6 +10,7 @@
         />
       </div>
       <img :src="sourceValue" v-if="sourceValue" alt="avatar" />
+      <img :src="headerImg" v-else alt="avatar" />
     </div>
     <a-button
       :class="`${prefixCls}-upload-btn`"
@@ -22,8 +23,12 @@
 
     <CopperModal
       @register="register"
-      @uploadSuccess="handleUploadSuccess"
+      @upload-success="handleUploadSuccess"
       :uploadApi="uploadApi"
+      :title="title"
+      :maxSize="5"
+      :circled="circled"
+      :aspectRatio="aspectRatio"
       :src="sourceValue"
     />
   </div>
@@ -46,13 +51,18 @@
   import { useI18n } from '/@/hooks/web/useI18n';
   import type { ButtonProps } from '/@/components/Button';
   import Icon from '/@/components/Icon';
+  import headerImg from '/@/assets/images/header.jpg';
 
   const props = {
     width: { type: [String, Number], default: '200px' },
     value: { type: String },
+    maxSize: { type: Number, default: 5 },
+    aspectRatio: { type: Number, default: 1 },
+    title: { type: String },
     showBtn: { type: Boolean, default: true },
     btnProps: { type: Object as PropType<ButtonProps> },
     btnText: { type: String, default: '' },
+    circled: { type: Boolean, default: true },
     uploadApi: { type: Function as PropType<({ file: Blob, name: string }) => Promise<void>> },
   };
 
@@ -62,7 +72,7 @@
     props,
     emits: ['update:value', 'change'],
     setup(props, { emit, expose }) {
-      const sourceValue = ref(props.value || '');
+      const sourceValue = ref(props.value || false);
       const { prefixCls } = useDesign('cropper-avatar');
       const [register, { openModal, closeModal }] = useModal();
       const { createMessage } = useMessage();
@@ -91,9 +101,9 @@
         },
       );
 
-      function handleUploadSuccess({ source }) {
+      function handleUploadSuccess({ source, data }) {
         sourceValue.value = source;
-        emit('change', source);
+        emit('change', source, data);
         createMessage.success(t('component.cropper.uploadSuccess'));
       }
 
@@ -109,7 +119,9 @@
         getClass,
         getImageWrapperStyle,
         getStyle,
+        circled: props.circled,
         handleUploadSuccess,
+        headerImg,
       };
     },
   });

+ 1 - 1
src/components/Drawer/src/BasicDrawer.vue

@@ -94,7 +94,7 @@
             opt.width = '100%';
           }
           const detailCls = `${prefixCls}__detail`;
-          opt.wrapClassName = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls;
+          opt.class = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls;
 
           if (!getContainer) {
             // TODO type error?

+ 1 - 2
src/components/Drawer/src/typing.ts

@@ -128,13 +128,12 @@ export interface DrawerProps extends DrawerFooterProps {
    * @type any (string | slot)
    */
   title?: VNodeChild | JSX.Element;
-
   /**
    * The class name of the container of the Drawer dialog.
    * @type string
    */
   wrapClassName?: string;
-
+  class?: string;
   /**
    * Style of wrapper element which **contains mask** compare to `drawerStyle`
    * @type object

+ 17 - 5
src/components/Form/src/BasicForm.vue

@@ -58,6 +58,7 @@
   import { createFormContext } from './hooks/useFormContext';
   import { useAutoFocus } from './hooks/useAutoFocus';
   import { useModalContext } from '/@/components/Modal';
+  import { useDebounceFn } from '@vueuse/core';
 
   import { basicProps } from './props';
   import { useDesign } from '/@/hooks/web/useDesign';
@@ -122,7 +123,7 @@
             if (!Array.isArray(defaultValue)) {
               schema.defaultValue = dateUtil(defaultValue);
             } else {
-              const def: moment.Moment[] = [];
+              const def: any[] = [];
               defaultValue.forEach((item) => {
                 def.push(dateUtil(item));
               });
@@ -225,16 +226,27 @@
         },
       );
 
+      watch(
+        () => formModel,
+        useDebounceFn(() => {
+          unref(getProps).submitOnChange && handleSubmit();
+        }, 300),
+        { deep: true },
+      );
+
       async function setProps(formProps: Partial<FormProps>): Promise<void> {
         propsRef.value = deepMerge(unref(propsRef) || {}, formProps);
       }
 
       function setFormModel(key: string, value: any) {
         formModel[key] = value;
-        const { validateTrigger } = unref(getBindValue);
-        if (!validateTrigger || validateTrigger === 'change') {
-          validateFields([key]).catch((_) => {});
-        }
+        // const { validateTrigger } = unref(getBindValue);
+        // console.log('key', key, schemas[3]);
+
+        // console.log('validateTrigger', validateTrigger, formModel);
+        // if (!validateTrigger || validateTrigger === 'change') {
+        //   validateFields([key]).catch((_) => {});
+        // }
       }
 
       function handleEnterPress(e: KeyboardEvent) {

+ 22 - 10
src/components/Form/src/components/ApiSelect.vue

@@ -1,8 +1,10 @@
 <template>
   <Select
-    @dropdownVisibleChange="handleFetch"
+    @dropdown-visible-change="handleFetch"
     v-bind="$attrs"
+    show-search
     @change="handleChange"
+    :filter-option="filterOption"
     :options="getOptions"
     v-model:value="state"
   >
@@ -57,6 +59,7 @@
       labelField: propTypes.string.def('label'),
       valueField: propTypes.string.def('value'),
       immediate: propTypes.bool.def(true),
+      alwaysLoad: propTypes.bool.def(false),
     },
     emits: ['options-change', 'change'],
     setup(props, { emit }) {
@@ -66,13 +69,18 @@
       const emitData = ref<any[]>([]);
       const attrs = useAttrs();
       const { t } = useI18n();
-
+      const filterOption = (input, option) => {
+        try {
+          return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
+        } catch (error) {
+          return false;
+        }
+      };
       // Embedded in the form, just use the hook binding to perform form verification
       const [state] = useRuleFormItem(props, 'value', 'change', emitData);
 
       const getOptions = computed(() => {
         const { labelField, valueField, numberToString } = props;
-
         return unref(options).reduce((prev, next: Recordable) => {
           if (next) {
             const value = next[valueField];
@@ -87,7 +95,7 @@
       });
 
       watchEffect(() => {
-        props.immediate && fetch();
+        props.immediate && !props.alwaysLoad && fetch();
       });
 
       watch(
@@ -115,16 +123,20 @@
           }
           emitChange();
         } catch (error) {
-          console.warn(error);
+          console.warn('error', error);
         } finally {
           loading.value = false;
         }
       }
 
-      async function handleFetch() {
-        if (!props.immediate && unref(isFirstLoad)) {
-          await fetch();
-          isFirstLoad.value = false;
+      async function handleFetch(visible) {
+        if (visible) {
+          if (props.alwaysLoad) {
+            await fetch();
+          } else if (!props.immediate && unref(isFirstLoad)) {
+            await fetch();
+            isFirstLoad.value = false;
+          }
         }
       }
 
@@ -136,7 +148,7 @@
         emitData.value = args;
       }
 
-      return { state, attrs, getOptions, loading, t, handleFetch, handleChange };
+      return { state, attrs, getOptions, loading, t, handleFetch, handleChange, filterOption };
     },
   });
 </script>

+ 2 - 0
src/components/Form/src/helper.ts

@@ -70,3 +70,5 @@ export function handleInputNumberValue(component?: ComponentType, val?: any) {
  * 时间字段
  */
 export const dateItemType = genType();
+
+export const defaultValueComponents = ['Input', 'InputPassword', 'InputSearch', 'InputTextArea'];

+ 7 - 7
src/components/Form/src/hooks/useFormEvents.ts

@@ -1,10 +1,10 @@
 import type { ComputedRef, Ref } from 'vue';
 import type { FormProps, FormSchema, FormActionType } from '../types/form';
 import type { NamePath } from 'ant-design-vue/lib/form/interface';
-import { unref, toRaw } from 'vue';
+import { unref, toRaw, nextTick } from 'vue';
 import { isArray, isFunction, isObject, isString } from '/@/utils/is';
 import { deepMerge } from '/@/utils';
-import { dateItemType, handleInputNumberValue } from '../helper';
+import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper';
 import { dateUtil } from '/@/utils/dateUtil';
 import { cloneDeep, uniqBy } from 'lodash-es';
 import { error } from '/@/utils/log';
@@ -37,9 +37,12 @@ export function useFormEvents({
     if (!formEl) return;
 
     Object.keys(formModel).forEach((key) => {
-      formModel[key] = defaultValueRef.value[key];
+      const schema = unref(getSchema).find((item) => item.field === key);
+      const isInput = schema?.component && defaultValueComponents.includes(schema.component);
+      formModel[key] = isInput ? defaultValueRef.value[key] || '' : defaultValueRef.value[key];
     });
-    clearValidate();
+    nextTick(() => clearValidate());
+
     emit('reset', toRaw(formModel));
     submitOnReset && handleSubmit();
   }
@@ -125,9 +128,6 @@ export function useFormEvents({
     const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
 
     const index = schemaList.findIndex((schema) => schema.field === prefixField);
-    const hasInList = schemaList.some((item) => item.field === prefixField || schema.field);
-
-    if (!hasInList) return;
 
     if (!prefixField || index === -1 || first) {
       first ? schemaList.unshift(schema) : schemaList.push(schema);

+ 2 - 1
src/components/Form/src/hooks/useFormValues.ts

@@ -33,7 +33,8 @@ export function useFormValues({
       if (isObject(value)) {
         value = transformDateFunc?.(value);
       }
-      if (isArray(value) && value[0]?._isAMomentObject && value[1]?._isAMomentObject) {
+
+      if (isArray(value) && value[0]?.format && value[1]?.format) {
         value = value.map((item) => transformDateFunc?.(item));
       }
       // Remove spaces

+ 0 - 0
src/components/Form/src/hooks/useLabelWidth.ts


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov