Browse Source

提交

master
宋国强 1 year ago
commit
036487b76d
  1. 71
      .commitlintrc.js
  2. 4
      .env.development
  3. 2
      .env.production
  4. 2
      .env.test
  5. 2
      .eslintignore
  6. 49
      .eslintrc.json
  7. 31
      .gitignore
  8. 9
      .prettierrc.js
  9. 7
      Dockerfile
  10. 7
      Dockerfile_prod
  11. 21
      LICENSE
  12. 260
      README.md
  13. 8
      aliasPassword.txt
  14. 25
      index.html
  15. 53
      nginx.conf
  16. 60
      nginx_prod.conf
  17. 79
      package.json
  18. BIN
      pdatest.keystore
  19. 6258
      pnpm-lock.yaml
  20. 100
      src/App.vue
  21. 111
      src/api/http.ts
  22. 13
      src/api/inLocation.ts
  23. 14
      src/api/location.ts
  24. 41
      src/api/login.ts
  25. 13
      src/api/outLocation.ts
  26. 10
      src/api/spareParts.ts
  27. 5
      src/api/sparePartsReturn.ts
  28. 11
      src/api/upload.ts
  29. 85
      src/api/uploadHttp.ts
  30. 6
      src/api/user.ts
  31. 85
      src/components/search/index.vue
  32. 469
      src/components/verifition/Verify.vue
  33. 14
      src/components/verifition/utils/ase.js
  34. 17
      src/components/verifition/utils/request.js
  35. 555
      src/components/verifition/verifyPoint/verifyPoint.vue
  36. 661
      src/components/verifition/verifySlider/verifySlider.vue
  37. 13
      src/env.d.ts
  38. 43
      src/main.ts
  39. 85
      src/manifest.json
  40. 68
      src/pages.json
  41. 526
      src/pages/inLocation/addForm.vue
  42. 148
      src/pages/inLocation/index.vue
  43. 274
      src/pages/index.vue
  44. 232
      src/pages/login.vue
  45. 531
      src/pages/outLocation/addForm.vue
  46. 166
      src/pages/outLocation/index.vue
  47. 188
      src/pages/scanCode/scanCode.vue
  48. 530
      src/pages/sparePartsReturn/addForm.vue
  49. 60
      src/plugins/auth.js
  50. 17
      src/plugins/index.js
  51. 73
      src/plugins/modal.js
  52. 32
      src/plugins/tab.js
  53. 19
      src/plugins/time.js
  54. BIN
      src/static/icon/screen.png
  55. BIN
      src/static/images/banner/banner01.jpg
  56. BIN
      src/static/images/banner/banner02.jpg
  57. BIN
      src/static/images/banner/banner03.jpg
  58. BIN
      src/static/images/banner/icon1.png
  59. BIN
      src/static/images/banner/icon2.png
  60. BIN
      src/static/images/banner/icon3.png
  61. BIN
      src/static/images/banner/icon4.png
  62. BIN
      src/static/images/banner/icon5.png
  63. BIN
      src/static/images/banner/icon6.png
  64. BIN
      src/static/images/banner/icon7.png
  65. 12
      src/static/images/banner/login_banner.svg
  66. BIN
      src/static/images/banner/logo-banner.png
  67. 6
      src/static/images/banner/u2335.svg
  68. 6
      src/static/images/banner/u2450.svg
  69. 6
      src/static/images/banner/u253_selected.svg
  70. BIN
      src/static/images/bg.jpg
  71. BIN
      src/static/images/default.jpg
  72. BIN
      src/static/images/icon1.png
  73. 1
      src/static/images/icon1.svg
  74. BIN
      src/static/images/icon2.png
  75. 1
      src/static/images/icon2.svg
  76. BIN
      src/static/images/icon3.png
  77. 1
      src/static/images/icon3.svg
  78. 1
      src/static/images/icon4.svg
  79. 1
      src/static/images/icon5.svg
  80. BIN
      src/static/images/icon6.png
  81. BIN
      src/static/images/icon7.png
  82. BIN
      src/static/images/icon8.png
  83. BIN
      src/static/images/mobile_bg.png
  84. BIN
      src/static/images/photo.png
  85. BIN
      src/static/images/profile.jpg
  86. BIN
      src/static/images/tabbar/tab_act_icon1.png
  87. BIN
      src/static/images/tabbar/tab_act_icon2.png
  88. BIN
      src/static/images/tabbar/tab_act_icon3.png
  89. BIN
      src/static/images/tabbar/tab_act_icon4.png
  90. BIN
      src/static/images/tabbar/tab_act_icon5.png
  91. BIN
      src/static/images/tabbar/tab_icon1.png
  92. BIN
      src/static/images/tabbar/tab_icon2.png
  93. BIN
      src/static/images/tabbar/tab_icon3.png
  94. BIN
      src/static/images/tabbar/tab_icon4.png
  95. BIN
      src/static/images/tabbar/tab_icon5.png
  96. 1
      src/store/index.ts
  97. 124
      src/store/modules/countStore.ts
  98. 2
      src/styles/vars/_base.less
  99. 2
      src/styles/vars/_base.scss
  100. 77
      src/uni.scss

71
.commitlintrc.js

@ -0,0 +1,71 @@
// @ts-check
/** @type {import('cz-git').UserConfig} */
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'body-leading-blank': [2, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 108],
'subject-empty': [2, 'never'],
'type-empty': [2, 'never'],
'subject-case': [0],
'type-enum': [
2,
'always',
[
'feat',
'fix',
'perf',
'style',
'docs',
'test',
'refactor',
'build',
'ci',
'chore',
'revert',
'wip',
'workflow',
'types',
'release'
]
]
},
prompt: {
// 中英文对照版
// messages: {
// type: '选择你要提交的类型 :',
// scope: '选择一个提交范围 (可选):',
// customScope: '请输入自定义的提交范围 :',
// subject: '填写简短精炼的变更描述 :\n',
// body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
// breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
// footerPrefixsSelect: '选择关联issue前缀 (可选):',
// customFooterPrefixs: '输入自定义issue前缀 :',
// footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
// confirmCommit: '是否提交或修改commit ?'
// },
// types: [
// { value: 'feat', name: 'feat: 新增功能' },
// { value: 'fix', name: 'fix: 修复缺陷' },
// { value: 'docs', name: 'docs: 文档变更' },
// { value: 'style', name: 'style: 代码格式' },
// { value: 'refactor', name: 'refactor: 代码重构' },
// { value: 'perf', name: 'perf: 性能优化' },
// { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
// {
// value: 'build',
// name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)'
// },
// { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
// { value: 'revert', name: 'revert: 回滚 commit' },
// {
// value: 'chore',
// name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)'
// },
// { value: 'wip', name: 'wip: 正在开发中' },
// { value: 'workflow', name: 'workflow: 工作流程改进' },
// { value: 'types', name: 'types: 类型定义文件修改' }
// ]
}
}

4
.env.development

@ -0,0 +1,4 @@
VITE_BASE_URL=http://localhost:12080/admin-api
#VITE_BASE_URL=http://dev.ccwin-in.com:25203/api/admin-api
VITE_BASE_URL_IMAGE=http://192.168.0.106:12080/admin-api

2
.env.production

@ -0,0 +1,2 @@
VITE_BASE_URL=http://dev.ccwin-in.com:25210/admin-api
VITE_BASE_URL_IMAGE=http://dev.ccwin-in.com:25210/admin-api

2
.env.test

@ -0,0 +1,2 @@
VITE_BASE_URL=http://dev.ccwin-in.com:25203/api/admin-api
VITE_BASE_URL_IMAGE=http://dev.ccwin-in.com:25203/api/admin-api

2
.eslintignore

@ -0,0 +1,2 @@
dist
*.nvue

49
.eslintrc.json

@ -0,0 +1,49 @@
{
"parser": "vue-eslint-parser",
"env": {
"browser": true,
"commonjs": true,
"es2021": true
},
"parserOptions": {
"ecmaVersion": 2021,
"parser": "@typescript-eslint/parser",
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"extends": [
"airbnb-base",
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:vue/vue3-essential",
"plugin:@typescript-eslint/recommended"
],
"plugins": ["vue", "@typescript-eslint", "todo-ddl"],
"rules": {
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"import/extensions": "off",
"quotes": ["warn", "single"],
"semi": ["warn", "never"],
"import/no-unresolved": "off",
"todo-ddl/diy": "warn",
"import/prefer-default-export": "off",
"no-param-reassign": "warn",
"import/no-extraneous-dependencies": "off",
"max-len": "warn",
"no-restricted-syntax": "off",
"no-bitwise": "off",
"camelcase": "off",
"no-case-declarations": "off",
"@typescript-eslint/no-namespace": "off",
"no-undef": "off",
"no-promise-executor-return": "off",
"vue/multi-word-component-names": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/ban-ts-comment": "off",
"linebreak-style": "off"
}
}

31
.gitignore

@ -0,0 +1,31 @@
.DS_Store
node_modules/
unpackage/
dist/
wxcomponents
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.project
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
.hbuilderx
.gitee
.github
package-lock.json
yarn.lock

9
.prettierrc.js

@ -0,0 +1,9 @@
module.exports = {
printWidth: 700, // 一行的字符数,如果超过会进行换行,默认为80
tabWidth: 2, // 一个 tab 代表几个空格数,默认为 2 个
useTabs: false, //是否使用 tab 进行缩进,默认为false,表示用空格进行缩减
singleQuote: true, // 字符串是否使用单引号,默认为 false,使用双引号
semi: false, // 行尾是否使用分号,默认为true
trailingComma: 'none', // 是否使用尾逗号
bracketSpacing: true // 对象大括号直接是否有空格,默认为 true,效果:{ a: 1 }
}

7
Dockerfile

@ -0,0 +1,7 @@
# 设置基础镜像
FROM win-nginx
WORKDIR /opt/eam-pda
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
# 将dist/build/h5/文件中的内容复制到 /opt/eam-pda 这个目录下面
COPY dist/build/h5/ /opt/eam-pda

7
Dockerfile_prod

@ -0,0 +1,7 @@
# 设置基础镜像
FROM win-nginx
WORKDIR /opt/eam-pda
COPY nginx_prod.conf /usr/local/nginx/conf/nginx.conf
# 将dist/build/h5/文件中的内容复制到 /opt/eam-pda 这个目录下面
COPY dist/build/h5/ /opt/eam-pda

21
LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 sugar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

260
README.md

@ -0,0 +1,260 @@
# uni-vue3-ts-template
uni-app Vue3 + TypeScript + Vite + Pinia + Unocss 模板项目
支持小程序,H5,App
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxODc4OTk1OQ==653218789959)
![Unocss](https://fastly.jsdelivr.net/gh/MellowCo/image-host/2022/202211121156442.png)
| H5 | 微信小程序 | App(iOS) | App(Android) |
| :-------------------------------------------------------------------------: | :-------------------------------------------------------------------------: | :-------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------: |
| ![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzE5Mzc4MzUyMQ==653193783521) | ![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzE5Mzc1Mzk1MQ==653193753951) | ![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxMDc2NTcwNg==653210765706) | <img src="https://img.cdn.sugarat.top/mdImg/MTY1MzIxMzkyOTQxNg==653213929416" width="360"/> |
其它模板
* Vue3的uni-app 纯js模板:[uni-app-template](https://github.com/ATQQ/uni-app-template)
* Vue3的Web应用模板:[vite-vue3-template](https://github.com/ATQQ/vite-vue3-template)
## Env Suggest
**Node >= 14.19**
**pnpm 7**
**Registry taobao - https://registry.npmmirror.com/**
## Use This Template
```sh
npx degit atqq/uni-vue3-ts-template#main my-uni-vue3-ts-vite-project
```
## Feature
### Prod
* [x] [Vue3](https://vuejs.org/)
* [x] [Pinia](https://pinia.vuejs.org/) - replace vuex
* [x] [Axios](https://github.com/axios/axios)
* UI/组件库
* [x] [uView](https://vkuviewdoc.fsq.pub/) - vk-uview-ui
* [ ] [uni-ui](https://github.com/dcloudio/uni-ui) - 待接入
### Dev
* [x] [Vite](https://github.com/vitejs/vite)
* [x] [TypeScript](https://github.com/microsoft/TypeScript/#readme)
* [x] [Sass](https://github.com/sass/sass)
* [x] [Less](https://github.com/less/less.js)
* [x] [Eslint](https://eslint.org/)
* [x] [Prettier](https://prettier.io/)
* [x] [Vitest](https://vitest.dev/) - replace jest
* [x] [unocss](https://github.com/unocss/unocss) - 即时按需原子 css 引擎
* [x] GitHooks [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks#readme)
* ~~LintStaged~~
* ~~StyleLint~~
## 使用
### 安装依赖
**建议使用pnpm,依赖安装速度更快**
```sh
npm i -g pnpm
```
```sh
pnpm install
```
**MAC M1(ARM芯片),其它操作系统无需关注**,正常运行需要手动安装 `esbuild-darwin-64`即可
```sh
pnpm add esbuild-darwin-64@0.15.13 -D
```
## 本地启动
### 微信小程序
```sh
# 构建出产物
pnpm dev:mp-weixin
```
> **Q1:** 如果dev的时候发现报错,可以尝试删除`node_modules`之后再在命令行中运行`pnpm install --shamefully-hoist`重新安装依赖再`pnpm dev:mp-weixin`
>
> [详细参考文档](https://pnpm.io/zh/faq#%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%883)
> **Q2:** 如果运行白屏,有报错信息 “app.js错误ReferenceError: regeneratorRuntime is not defined”
>
> 参考[解决方案](https://blog.csdn.net/FUFCY/article/details/125160828) 给微信小程序IDE开启**增强编译选项**
然后将编译结果`dist/dev/mp-weixin`导入微信开发者工具即可运行
<details>
<summary>点击查看 导入详细步骤</summary>
![图片](https://img.cdn.sugarat.top/mdImg/MTYzNzQxNjc3MjA4Mw==637416772083)
![图片](https://img.cdn.sugarat.top/mdImg/MTYzNzQxNjg4MTUwNA==637416881504)
![图片](https://img.cdn.sugarat.top/mdImg/MTYzNzQxNjY3OTY0NQ==637416679645)
</details>
### H5
```sh
# CSR
pnpm dev:h5
# SSR
pnpm dev:h5:ssr
```
根据提示,打开对应地址即可访问
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxMTE0MDEzMg==653211140132)
### App
>**Q1:** 如启动到App侧有报错?
>请更新至最新的HBuilderX-Alpha客户端
#### 安装一些必要工具
需要使用 `uni-app` 官方提供的 [HBuilderX](https://www.dcloud.io/hbuilderx.html) 启动项目
**Android模拟器在MacOSX、Windows上都可以安装;iOS模拟器只能在MacOSX上安装。**
先安装相关模拟器,[详细参考文档](https://hx.dcloud.net.cn/Tutorial/App/installSimulator)
* 安卓:[夜神模拟器](https://www.yeshen.com/blog/)
* iOS:Mac上安装Xcode
准备就绪后,使用 HBuilderX 打开项目
#### iOS模拟器运行
通过顶部菜单栏,找到运行入口
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxMjk1MTgzNw==653212951837)
选择一个目标设备,点击启动即可
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxMjk3NDM0NQ==653212974345)
#### Android模拟器运行
这里以[夜神模拟器](https://www.yeshen.com/blog/)为例
<details>
<summary>点击查看 详细步骤</summary>
先通过 HBuilderX 修改模拟器端口为 `62001`
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxNDAzMjIwNg==653214032206)
打开夜神模拟器
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxNDA5OTYxNg==653214099616)
选择运行到 Android 基座
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxNDEzMzI0OA==653214133248)
选择已经打开的模拟器,点击运行即可
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxNDIxNjczNw==653214216737)
![图片](https://img.cdn.sugarat.top/mdImg/MTY1MzIxMzkyOTQxNg==653213929416)
</details>
## 打包构建
### 微信小程序
```
pnpm build:mp-weixin
```
### H5
```sh
# CSR
pnpm build:h5
# SSR
pnpm build:h5:ssr
```
### App
基于 `HBuilderX` 参考[官方文档](https://hx.dcloud.net.cn/Tutorial/App/SafePack)进行进一步的操作
其它更多运行脚本 查看 [package.json](./package.json)中的scripts
## css预处理
### 已配置`scss`和`less`全局变量
```typescript
// vite.config.ts
export default defineConfig({
// ......
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "@/static/styles/variables.scss";'
},
less: {
additionalData: '@import "@/static/styles/variables.less";'
}
}
}
})
```
`additionalData`的值是文件的路径,可以按照自己业务需求去修改,**如果项目样式变量分的比较细,可以使用一个样式文件引入多个变量样式文件,然后在这里引入入口文件**
## 别名配置
如果我们想要在`import`的时候 src 的路径简写成`@`,下面的就是配置 vite 的别名,[属性类型请查看vite文档](https://vitejs.cn/config/#resolve-alias)
- `@` 代替 `./src`
- `@components`代替`./src/components`
```typescript
// vite.config.ts
export default defineConfig({
// ......
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components')
}
}
})
```
例子:
```diff
// pages/index/index.vue
- import Hello from '../../components/hello/index.vue'
+ import Hello from '@/components/hello/index.vue'
// 或者
+ import Hello from '@components/hello/index.vue'
```
### ts
如果是使用ts开发,这样还不够,ts不会识别路径的别名,显示找不到模块的报错,这个时候需要修改 `tsconfig.json` 文件,纠正下路径才可以。
```diff
// tsconfig.json
{
// ......
"compilerOptions": {
// ......
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["src/*"],
+ "@components/*": ["src/components/*"]
}
},
}
```
添加 `baseUrl``paths` 参数,就可以完美解决编辑器的报错提示了!
## 原子化css
* [unocss](https://github.com/unocss/unocss) - 即时按需原子 css 引擎
* [unocss-preset-weapp](https://github.com/MellowCo/unocss-preset-weapp) - 兼容小程序 unocss 预设
> 支持小程序,h5,app
![](https://fastly.jsdelivr.net/gh/MellowCo/image-host/2022/202211121156442.png)

8
aliasPassword.txt

@ -0,0 +1,8 @@
证书名称:pdatest.keystore
证书别名:pdatestalias
证书密码:092134
SHA1: 53:30:B7:A6:0B:10:FA:0A:5A:3A:2F:4A:E5:21:96:EC:79:5B:41:C1
SHA256: C4:85:45:66:D5:FC:6E:FB:C8:45:5D:FA:41:8D:94:6D:E5:C1:41:CE:D0:E3:4D:B3:F9:3B:68:6A:1B:E2:43:86
Android 包名:com.eampda.uniapp
Android 应用签名:aa65e187685c2088b82d1a8c143bbabe//还没弄
ios 包名:com.eam.bundleld//还没弄

25
index.html

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app">
<!--app-html-->
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

53
nginx.conf

@ -0,0 +1,53 @@
user root;
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
charset utf-8,gbk;
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" "$request_time $upstream_response_time"';
proxy_cache_path /opt/nginx_cache/ levels=1:2 keys_zone=my_zone:10m inactive=300s max_size=5g;
access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 600s;
client_max_body_size 200m;
gzip on;
gzip_min_length 10k;
gzip_comp_level 9;
gzip_buffers 4 16k;
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
upstream eam {
server localhost:90 weight=10 max_fails=3 fail_timeout=10s;
}
server {
listen 82;
server_name_in_redirect off;
server_name dev.ccwin-in.com;
location /api/ {
proxy_pass http://eam/;
proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
proxy_set_header X-Forwared-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
}
location / {
proxy_cache my_zone;
proxy_cache_valid 200 304 12h;
proxy_cache_key $host$uri$is_args$args;
try_files $uri $uri/ /index.html;
root /opt/eam-pda;
index index.html index.htm;
}
}
}

60
nginx_prod.conf

@ -0,0 +1,60 @@
user root;
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
charset utf-8,gbk;
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" "$request_time $upstream_response_time"';
proxy_cache_path /opt/nginx_cache/ levels=1:2 keys_zone=my_zone:10m inactive=300s max_size=5g;
access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 600s;
client_max_body_size 200m;
gzip on;
gzip_min_length 10k;
gzip_comp_level 9;
gzip_buffers 4 16k;
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
upstream eam {
server localhost:90 weight=10 max_fails=3 fail_timeout=10s;
}
server {
listen 82;
server_name_in_redirect off;
server_name _;
location /api/ {
proxy_pass http://eam/;
proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
proxy_set_header X-Forwared-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
}
location /profile/ {
proxy_cache my_zone;
proxy_cache_valid 200 304 12h;
proxy_cache_key $host$uri$is_args$args;
alias /opt/profile/;
index index.html index.htm;
}
location / {
proxy_cache my_zone;
proxy_cache_valid 200 304 12h;
proxy_cache_key $host$uri$is_args$args;
try_files $uri $uri/ /index.html;
root /opt/eam-pda;
index index.html index.htm;
}
}
}

79
package.json

@ -0,0 +1,79 @@
{
"name": "闻荫APP",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "uni",
"dev:mp-weixin": "uni -p mp-weixin",
"dev:app": "uni -p app",
"dev:custom": "uni -p",
"test": "uni build --mode test",
"test:mp-weixin": "uni build -p mp-weixin",
"test:app": "uni build -p app",
"test:custom": "uni build -p",
"prod": "uni build --mode production",
"prod:mp-weixin": "uni build -p mp-weixin --mode production",
"prod:app": "uni build -p app --mode production",
"prod:custom": "uni build -p --mode production"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-app-plus": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-components": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-h5": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-mp-alipay": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-mp-baidu": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-mp-lark": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-mp-qq": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3060920221114001",
"axios": "^0.27.2",
"cz-git": "^1.4.1",
"or": "^0.2.0",
"pinia": "^2.0.35",
"vk-uview-ui": "^1.3.7",
"vue": "^3.2.41",
"vue-demi": "latest",
"vue-i18n": "^9.1.9",
"vuex": "^4.0.2"
},
"devDependencies": {
"@commitlint/cli": "^17.4.2",
"@commitlint/config-conventional": "^17.4.2",
"@dcloudio/types": "^3.0.16",
"@dcloudio/uni-automator": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-cli-shared": "3.0.0-alpha-3060920221114001",
"@dcloudio/uni-stacktracey": "3.0.0-alpha-3060920221114001",
"@dcloudio/vite-plugin-uni": "3.0.0-alpha-3060920221114001",
"@types/node": "^17.0.45",
"@typescript-eslint/eslint-plugin": "^5.30.3",
"@typescript-eslint/parser": "^5.30.3",
"@vitejs/plugin-vue": "^2.3.3",
"@vitest/ui": "^0.10.5",
"c8": "^7.11.3",
"czg": "^1.4.1",
"eslint": "^8.19.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-todo-ddl": "^1.1.1",
"eslint-plugin-vue": "^9.1.1",
"jsdom": "^24.0.0",
"less": "^4.1.3",
"prettier": "^2.7.1",
"sass": "^1.53.0",
"simple-git-hooks": "^2.8.1",
"typescript": "^4.7.4",
"unocss": "^0.46.4",
"unocss-preset-weapp": "^0.2.1",
"vite": "^3.1.8",
"vite-plugin-eslint": "^1.6.1",
"vitest": "^0.16.0"
},
"simple-git-hooks": {
"commit-msg": "npx --no-install commitlint --edit \"$1\""
}
}

BIN
pdatest.keystore

Binary file not shown.

6258
pnpm-lock.yaml

File diff suppressed because it is too large

100
src/App.vue

@ -0,0 +1,100 @@
<script setup lang="ts">
import {
onLaunch,
onShow,
onHide
} from '@dcloudio/uni-app'
import {
getCurrentInstance
} from 'vue'
import {
getAccessToken
} from '@/utils/auth'
const { proxy } = getCurrentInstance()
import { storeToRefs } from 'pinia'
import { useCountStore } from '@/store'
// store
const store = useCountStore()
onLaunch(async () => {
// #ifdef MP-WEIXIN
if (uni.canIUse('getUpdateManager')) {
const updateManager = uni.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
if (res.hasUpdate) {
updateManager.onUpdateReady(function () {
uni.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success: function (res) {
if (res.confirm) {
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
uni.showModal({
title: '已经有新版本了哟~',
content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~'
})
})
}
})
} else {
uni.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
// #endif
// plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
// _this.$post('common/upApp', {
// version: widgetInfo.version,
// }).then(res => {
// if (res.status == 0) {
// if (res.data.code == 0) {
// uni.downloadFile({
// url: res.data.download,
// success: (downloadResult) => {
// if (downloadResult.statusCode === 200) {
// plus.runtime.install(downloadResult
// .tempFilePath, {
// force: true
// },
// function() {
// plus.runtime.restart();
// },
// function(e) {
// });
// }
// }
// });
// }
// }
// })
// });
if (getAccessToken()) {
await store.GetPermissionInfo().then(res => {
uni.setStorageSync('permissionInfo',res.permissions)
uni.setStorageSync('roles',res.roles)
}).catch(() => { })
await store.GetInfo().then(res => {
}).catch(() => { })
}
// onLaunchonLoad
proxy.$isResolve();
})
onShow(() => {
})
onHide(() => {
})
</script>
<style lang="scss">
@import 'vk-uview-ui/index.scss';
</style>

111
src/api/http.ts

@ -0,0 +1,111 @@
import axios from 'axios'
import { getFullURL } from '@/utils/http'
import { getAccessToken, removeToken } from '@/utils/auth'
const instance = axios.create({
baseURL: import.meta.env.VITE_BASE_URL,
adapter(config) {
const { url, method, data, params, headers, baseURL, paramsSerializer } =
config
return new Promise((resolve, reject) => {
uni.request({
method: method!.toUpperCase() as any,
url: getFullURL(baseURL || '', url!, params, paramsSerializer),
header: headers,
data,
dataType: 'json',
responseType: config.responseType,
success: (res : any) => {
resolve(res)
},
fail: (error : any) => {
reject(error)
}
})
})
}
})
/**
*
*/
instance.interceptors.request.use((config) => {
const { method, params, url } = config
// 附带鉴权的token
const headers : any = {
token: getAccessToken(),
'Authorization': 'Bearer ' + getAccessToken()
}
if (uni.getStorageSync('openId')) {
headers['openId'] = uni.getStorageSync('openId')
}
// 不缓存get请求
if (method === 'get') {
headers['Cache-Control'] = 'no-cache'
}
// delete请求参数放入body中
if (method === 'delete') {
headers['Content-type'] = 'application/json;'
Object.assign(config, {
data: params,
params: {}
})
}
return {
...config,
headers
}
})
/**
*
*/
instance.interceptors.response.use((v) => {
const code = v.data?.code || 200
if (code === 401) {
// alert('即将跳转登录页。。。', '登录过期')
// setTimeout(redirectHome, 1500)
removeToken()
uni.showModal({
title: '系统提示',
content: '登录状态已过期,您可以继续留在该页面,或者重新登录',
cancelText: '关闭',
confirmText: '重新登录',
success: function (res) {
if (res.confirm) {
uni.reLaunch({ url: '/pages/login' })
}
}
})
return v.data
} else if (code === 500) {
uni.showToast({
title: v.data.msg,
icon: 'none'
})
return v.data
} else if (code !== 200) {
uni.showToast({
title: v.data.msg,
icon: 'none'
})
return v.data
}
// @ts-ignore
if ((v.status || v.statusCode) === 200) {
return v.data
}else{
}
return Promise.reject(v)
},error=>{
uni.showToast({
title: '网络错误',
icon: 'none'
})
})
export default instance

13
src/api/inLocation.ts

@ -0,0 +1,13 @@
import http from './http'
// 获取采购订单分页列表
export function getInLocationPage(params) {
return http.get('/eam/item-order-main/getPdaPage',{params})
}
// 获取采购订单分页列表
export function getInLocationDetail(id) {
return http.get('/eam/item-order-main/getPdaDetailsById?id='+id)
}
// 入库新增
export function inLocationCreat(data) {
return http.post('/eam/item-order-main/inOperation',data)
}

14
src/api/location.ts

@ -0,0 +1,14 @@
import http from './http'
// 获取库位
export function getLocation(number) {
return http.get('/eam/location/scanCodeByNumber?number='+number)
}
// 出库获取库位
export function getOutLocation(data) {
return http.post('/eam/location/outScanCodeByNumber',data)
}
// 首页扫码获取详情
export function pdaItemAndLocation(number) {
return http.get('/eam/location/pdaItemAndLocation?number='+number)
}

41
src/api/login.ts

@ -0,0 +1,41 @@
import http from './http'
// 登录方法
export function login(username, password, captchaVerification, tenantName, rememberMe, code, uuid) {
const data = {
username,
password,
captchaVerification,
tenantName,
rememberMe,
code,
uuid,
}
return http.post('/system/auth/login', data)
}
// 获取用户详细信息
export function getInfo() {
return http.get('/system/user/profile/get')
}
// 获取权限
export function getPermissionInfo() {
return http.get('/system/auth/get-permission-info')
}
// 退出方法
export function logout() {
return http.post('/system/auth/logout')
}

13
src/api/outLocation.ts

@ -0,0 +1,13 @@
import http from './http'
// 获取领用出库分页列表
export function getOutLocationPage(params) {
return http.get('/eam/item-apply-request-main/getAppOutOperaPage',{params})
}
// 获取领用出库详情
export function getOutLocationDetail(params) {
return http.get('/eam/item-apply-request-main/appGetByNumber',{params})
}
// 出库新增
export function outLocationCreat(data) {
return http.post('/eam/item-apply-request-main/outOperation',data)
}

10
src/api/spareParts.ts

@ -0,0 +1,10 @@
import http from './http'
// 获取备件信息
export function getSparePartsInfo(params) {
return http.get('/eam/item/inScanCodeByNumber',{params})
}
// 备件归还获取备件信息
export function getSparePartsReturnInfo(params) {
return http.get('/eam/item/scanCodeByNumber',{params})
}

5
src/api/sparePartsReturn.ts

@ -0,0 +1,5 @@
import http from './http'
// 归还
export function sparePartsReturn(data) {
return http.post('/eam/item-apply-request-main/inOperation',data)
}

11
src/api/upload.ts

@ -0,0 +1,11 @@
import upload from '@/api/uploadHttp'
// import request from '@/utils/request'
// 上传
export function uploadFile(data) {
return upload({
url: '/infra/file/upload',
method: 'post',
filePath:data.filePath,
name: data.name
})
}

85
src/api/uploadHttp.ts

@ -0,0 +1,85 @@
import axios from 'axios'
import { getFullURL } from '@/utils/http'
import { getAccessToken } from '@/utils/auth'
// const baseURL1 = import.meta.env.VITE_BASE_URL
const upload = axios.create({
baseURL: import.meta.env.VITE_BASE_URL,
adapter(config) {
const { url, method, data, params, headers, baseURL, paramsSerializer, filePath } =
config
headers['tenant-id'] = '1';
return new Promise((resolve, reject) => {
uni.uploadFile({
url: getFullURL(baseURL || '', url!, params, paramsSerializer),
filePath: filePath,
name: 'file',
header: headers,
formData: {
'user': 'test'
},
success: (res) => {
resolve(res)
},
fail: (error) => {
reject(error)
}
})
})
}
})
/**
*
*/
upload.interceptors.request.use((config) => {
const { method, params, url } = config
// 附带鉴权的token
const headers : any = {
token: getAccessToken(),
'Authorization': 'Bearer ' + getAccessToken()
}
if (uni.getStorageSync('openId')) {
headers['openId'] = uni.getStorageSync('openId')
}
// 不缓存get请求
if (method === 'get') {
headers['Cache-Control'] = 'no-cache'
}
// delete请求参数放入body中
if (method === 'delete') {
headers['Content-type'] = 'application/json;'
Object.assign(config, {
data: params,
params: {}
})
}
return {
...config,
headers
}
})
/**
*
*/
upload.interceptors.response.use((v) => {
if (v.data?.code === 401) {
// alert('即将跳转登录页。。。', '登录过期')
// setTimeout(redirectHome, 1500)
return v.data
}
// @ts-ignore
if ((v.status || v.statusCode) === 200) {
return v.data
}
// alert(v.statusText, '网络错误')
return Promise.reject(v)
})
export default upload

6
src/api/user.ts

@ -0,0 +1,6 @@
import http from './http'
// 归还人员
export function getReverterUser() {
return http.get('/system/user/list-all-simple')
}

85
src/components/search/index.vue

@ -0,0 +1,85 @@
<template>
<view class="content">
<view class="screen-input">
<u-search
v-model='keyWord'
:show-action='false'
:bg-color="searchData.bgBolor ||'white'"
:border-color="searchData.borderColor ||'#E4E4E4'"
:shape="searchData.shape ||'square'"
:height="searchData.height || 80"
:placeholder="searchData.placeholder ||'请输入设备名称'"
:clearabled="true"
@search='search'
@clear='clear'
>
</u-search>
</view>
<view class="screen-btn" @click="screen" v-if="isShowScreen">
<image src="../../static/icon/screen.png" mode="widthFix"></image>
<view>筛选</view>
</view>
</view>
</template>
<script>
export default {
props: {
searchData:{
type: Object,
default:()=>{return {}},
require:false
},
isShowScreen: {
type: Boolean,
default:()=>{return true},
require:false
},
},
data() {
return {
keyWord: '',
}
},
methods: {
//
search() {
this.$emit('search', this.keyWord)
},
//
clear() {
this.$emit('search', '')
},
//
screen() {
this.$emit('screen')
}
}
}
</script>
<style lang="scss" scoped>
.content {
padding: 20rpx;
display: flex;
align-items: center;
background: white;
.screen-input {
flex: 1;
width: 0px;
}
.screen-btn {
display: flex;
align-items: center;
margin-left:20rpx;
image {
width: 30rpx;
margin-right: 6rpx;
}
}
}
</style>

469
src/components/verifition/Verify.vue

File diff suppressed because one or more lines are too long

14
src/components/verifition/utils/ase.js

@ -0,0 +1,14 @@
import CryptoJS from 'crypto-js'
/**
* @word 要加密的内容
* @keyWord String 服务器随机返回的关键字
* */
export function aesEncrypt(word, keyWord = "XwKsGlMcdPMEhR1B") {
var key = CryptoJS.enc.Utf8.parse(keyWord);
var srcs = CryptoJS.enc.Utf8.parse(word);
var encrypted = CryptoJS.AES.encrypt(srcs, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}

17
src/components/verifition/utils/request.js

@ -0,0 +1,17 @@
import config from '@/config'
const baseUrl = config.baseUrl
export const myRequest = (option = {}) => {
return new Promise((reslove, reject) => {
uni.request({
url: baseUrl + option.url,
data: option.data,
method: option.method || "GET",
success: (result) => {
reslove(result)
},
fail: (error) => {
reject(error)
}
})
})
}

555
src/components/verifition/verifyPoint/verifyPoint.vue

File diff suppressed because one or more lines are too long

661
src/components/verifition/verifySlider/verifySlider.vue

File diff suppressed because one or more lines are too long

13
src/env.d.ts

@ -0,0 +1,13 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
interface ImportMetaEnv {
VITE_TITLE: string
VITE_BASE_URL: string
}

43
src/main.ts

@ -0,0 +1,43 @@
import { createSSRApp } from 'vue'
import * as Pinia from 'pinia'
// @ts-ignore
import uView from 'vk-uview-ui'
import App from './App.vue'
import tab from './plugins/tab'
import modal from './plugins/modal'
import time from './plugins/time'
import auth from './plugins/auth'
// unocss
import 'uno.css'
import { accessTimeInAnHour, getNowFormatDate } from "./utils/dateTime";
export function createApp() {
const app = createSSRApp(App)
app.use(Pinia.createPinia())
app.use(uView)
// 解决onLaunch和onLoad异步问题
app.config.globalProperties.$onLaunched = new Promise(resolve => {
app.config.globalProperties.$isResolve = resolve
})
// 页签操作
app.config.globalProperties.$tab = tab
// 模态框对象
app.config.globalProperties.$modal = modal
// 时间对象
app.config.globalProperties.$time = time
app.config.globalProperties.$auth = auth
return {
app,
// uni-app 官方文档示例 https://zh.uniapp.dcloud.io/tutorial/vue3-pinia.html#%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86-pinia
Pinia // 此处必须将 Pinia 返回
}
}

85
src/manifest.json

@ -0,0 +1,85 @@
{
"name" : "富维汽车镜",
"appid" : "__UNI__0DC0349",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
"compatible" : {
"ignoreVersion" : true
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"ad" : {}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wx6176535b0b0153f0",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3",
"h5" : {
"template" : "index.html",
"devServer" : {
"port" : 9020
}
}
}

68
src/pages.json

@ -0,0 +1,68 @@
{
"pages": [{
"path": "pages/index",
"style": {
"navigationBarTitleText": "首页",
"navigationStyle": "custom"
}
}, {
"path": "pages/login",
"style": {
"navigationStyle": "custom"
}
}, {
"path": "pages/inLocation/index",
"style": {
"navigationStyle": "custom",
"navigationBarBackgroundColor": "#409eff",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/inLocation/addForm",
"style": {
"navigationBarTitleText": "入库信息",
"navigationBarBackgroundColor": "#409eff",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/sparePartsReturn/addForm",
"style": {
"navigationBarTitleText": "备件归还",
"navigationBarBackgroundColor": "#409eff",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/outLocation/index",
"style": {
"navigationBarTitleText": "领用出库",
"navigationBarBackgroundColor": "#409eff",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/outLocation/addForm",
"style": {
"navigationBarTitleText": "出库信息",
"navigationBarBackgroundColor": "#409eff",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/scanCode/scanCode",
"style": {
"navigationBarTitleText": "扫码详情",
"navigationBarBackgroundColor": "#409eff",
"navigationBarTextStyle": "white"
}
}],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "",
"navigationBarBackgroundColor": "#fff",
"backgroundColorBottom": "#f5f5f5"
},
"easycom": {
"custom": {
"^u-(.*)": "vk-uview-ui/components/u-$1/u-$1.vue"
}
}
}

526
src/pages/inLocation/addForm.vue

@ -0,0 +1,526 @@
<template>
<!-- 添加维修工单 -->
<view class="add-form-container">
<u-form :model="form" ref="formRef" label-width="160rpx">
<u-form-item label="批次号" prop="number">
<u-input v-model="form.number" placeholder="请输入批次号" />
</u-form-item>
<u-form-item label="供应商" prop="supplierName">
<u-input v-model="form.supplierName" placeholder="请输入供应商" />
</u-form-item>
</u-form>
<view class="list">
<view class="title">
<span>*</span>订单信息
</view>
<view class="item " v-for="(item,index) in orderList" :key="index">
<view class="item-box">
<view class="spare-title">
<view class="title-txt">
备件名称{{item.itemName}}
</view>
</view>
<u-row gutter="16">
<!-- <u-col :span="24">
<view class="dec">
库位{{item.locationNumber}}
</view>
</u-col> -->
<u-col :span="24">
<view class="dec">
已入库数量:{{item.deliveryQty}}
</view>
</u-col>
<u-col :span="24">
<view class="dec">
采购数量:{{item.qty}}
</view>
</u-col>
</u-row>
</view>
</view>
</view>
<view class="list">
<view class="title">
<span>*</span>申请备件
</view>
<view class="item " v-for="(item,index) in form.itemNumbers" :key="index">
<view class="item-box">
<view class="spare-title">
<view class="title-txt">
备件名称{{item.itemName}}
</view>
</view>
<u-row gutter="16">
<u-col :span="24">
<view class="dec">
入库数量{{item.qty}}
</view>
</u-col>
<u-col :span="24">
<view class="dec">
采购数量{{item.applyQty}}
</view>
</u-col>
</u-row>
</view>
<u-icon name="minus-circle" color="#aaaaaa" size="60" @click="delSpareParts(index)"></u-icon>
</view>
<view class="add-btn">
<u-button type="primary" @click="open"><u-icon name="plus-circle" color="#ffffff"
size="36"></u-icon>添加备件</u-button>
</view>
</view>
<view class="footer">
<view class="btns">
<button class="reset" @click="reset">重置</button>
<button class="sure" @click="submit" :loading='loading' :disabled='loading'>确定</button>
</view>
<view style="height: constant(safe-area-inset-bottom); height: env(safe-area-inset-bottom);"></view>
</view>
<!-- 添加备件 -->
<u-popup v-model="isPopupShow" mode="center" border-radius="14">
<view class="popup-title">添加备件</view>
<scroll-view scroll-y="true" style="max-height:60vh;">
<view class="popup">
<u-form :model="form1" ref="form1Ref" label-width="160rpx">
<u-form-item :label="`备件编号`" prop="itemNumber" required>
<view class="select">
<u-input v-model="form1.itemNumber" placeholder="请选择备件" @blur='blur1()'
@confirm="handelScanMsg1" :focus='isFocus' />
</view>
</u-form-item>
<u-form-item :label="`备件名称`" prop="itemName" required class="disabled">
<view class="select">
<u-input v-model="form1.itemName" placeholder="根据备件编号获取" disabled />
</view>
</u-form-item>
<u-form-item label="库位" prop="locationNumber" required v-if="isShow">
<u-input v-model="form1.locationNumber" placeholder="请输入库位" @blur='blur()'
@confirm="handelScanMsg" />
</u-form-item>
<u-form-item label="采购数量" prop="applyQty" required class="disabled">
<u-input v-model="form1.applyQty" type="number" disabled placeholder="请输入采购数量" />
</u-form-item>
<u-form-item label="已入库数量" prop="deliveryQty" required class="disabled">
<u-input v-model="form1.deliveryQty" type="number" disabled placeholder="请输入已入库数量" />
</u-form-item>
<u-form-item label="入库数量" prop="qty" required>
<u-input v-model="form1.qty" type="number" placeholder="请输入入库数量" />
</u-form-item>
<u-form-item label="描述" prop="qty">
<u-input v-model="form1.describes" placeholder="请输入描述" />
</u-form-item>
</u-form>
</view>
</scroll-view>
<view class="popup-footer">
<view @click="isPopupShow = false">取消</view>
<view class="sure" @click="addSpare">确认</view>
</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
import {
onLoad
} from '@dcloudio/uni-app'
import {
ref,
getCurrentInstance
} from 'vue'
import * as inLocationApi from "@/api/inLocation"
import * as sparePartsApi from "@/api/spareParts"
import * as locationApi from "@/api/location"
const { proxy } = getCurrentInstance()
const loading = ref(false)
const orderList = ref([])//
//
const isPopupShow = ref(false)
const form = ref({
id: '',
number: '',
itemNumbers: [],
supplierName:''
})
const form1 = ref({
itemNumber: "",
itemName: '',
locationNumber: '',
applyQty: '',
deliveryQty: '',
qty: ''
})
const itemNumber = ref()
const isShow = ref(false)
const locationList = ref([])//
const locationItem = ref('')//
const isFocus = ref(false)
const msg = ref('')
function submit() {
if (form.value.itemNumbers.length === 0) {
proxy.$modal.showToast('请选择备件')
return;
}
proxy.$modal.confirm('是否添加入库信息').then(() => {
proxy.$modal.loading('加载中')
loading.value = true
inLocationApi.inLocationCreat(form.value).then((res) => {
proxy.$modal.closeLoading()
if (res.data) {
proxy.$modal.showToast('添加成功')
setTimeout(() => {
proxy.$tab.navigateBack()
loading.value = false
}, 1500)
} else {
proxy.$modal.showToast('添加失败')
loading.value = false
}
}).catch(() => {
proxy.$modal.closeLoading()
loading.value = false
})
})
}
//
function reset() {
form.value.supplierName = ''
form.value.itemNumbers = []
}
//
async function getInLocationDetail() {
await inLocationApi.getInLocationDetail(form.value.id).then(res => {
orderList.value = res.data
}).catch((err) => { })
}
//
function open() {
form1.value = {
itemNumber: "",
itemName: '',
locationNumber: '',
applyQty: '',
deliveryQty: '',
qty: ''
}
isPopupShow.value = true
isShow.value = false
isFocus.value = true
}
//
function addSpare() {
//
if (!form1.value.itemNumber) {
proxy.$modal.showToast('请选择备件')
return;
}
if (!form1.value.itemName) {
proxy.$modal.showToast(msg.value)
return;
}
if (!form1.value.locationNumber) {
proxy.$modal.showToast('请选择库位')
return;
}
if (!locationItem.value || locationItem.value.isInAccount === 'FALSE') {
proxy.$modal.showToast('该库位属于帐外库,请选择帐内库')
return;
}
if (itemNumber.value) {
proxy.$modal.showToast('该库位已绑定过备件')
return;
}
if (!form1.value.qty) {
proxy.$modal.showToast(`请输入数量`)
return;
}
if (Number(form1.value.qty) + Number(form1.value.deliveryQty) > Number(form1.value.applyQty)) {
proxy.$modal.showToast('已入库数量和入库数量不可大于采购数量')
return;
}
if (form.value.itemNumbers && form.value.itemNumbers.length > 0) {
let arr = form.value.itemNumbers.filter(item => item.itemNumber == form1.value.itemNumber)
if (arr && arr.length > 0) {
proxy.$modal.showToast('该备件已添加')
return;
}
let arr1 = orderList.value.filter(item => item.itemNumber == form1.value.itemNumber)
if (!arr1 || (arr1 && arr1.length == 0)) {
proxy.$modal.showToast('订单信息没有该备件')
return;
}
}
form.value.itemNumbers.push(form1.value)
isPopupShow.value = false
}
//
function delSpareParts(index) {
form.value.itemNumbers.splice(index, 1)
}
function getLocation() {
locationApi.getLocation(form1.value.locationNumber).then(res => {
if (!res.data) {
msg.value = res.msg
proxy.$modal.showToast(res.msg)
return;
}
locationItem.value = res.data
form1.value.areaNumber = locationItem.value.areaNumber
itemNumber.value = res.data.itemNumber || ''
//
if (form.value.itemNumbers && form.value.itemNumbers.length > 0) {
let arr = form.value.itemNumbers.filter(item => item.locationNumber == form1.value
.locationNumber)
if (arr && arr.length > 0) {
itemNumber.value = 1
} else {
itemNumber.value = res.data.itemNumber || ''
}
} else {
itemNumber.value = res.data.itemNumber || ''
}
}).catch((err) => { })
}
function blur() {
if (form1.value.locationNumber) {
getLocation()
}
}
//
function handelScanMsg() {
getLocation()
}
//
function getSparePartsInfo() {
sparePartsApi.getSparePartsInfo({
number: form1.value.itemNumber,
id: form.value.id
}).then(res => {
if (!res.data) {
itemNumber.value = ''
form1.value.areaNumber = ''
form1.value.locationNumber = '';
form1.value.itemName = ''
return;
}
itemNumber.value = ''
form1.value.itemName = res.data.itemName
form1.value.deliveryQty = res.data.deliveryQty
form1.value.applyQty = res.data.applyQty
//
locationItem.value = res.data.list.filter(item => item.isInAccount === 'TRUE')[0]
if (locationItem.value) {
form1.value.areaNumber = locationItem.value.areaNumber
form1.value.locationNumber = locationItem.value.locationNumber
isShow.value = false
} else {
form1.value.areaNumber = ''
form1.value.locationNumber = ''
isShow.value = true
}
}).catch((err) => {
itemNumber.value = ''
form1.value.areaNumber = ''
form1.value.itemName = ''
form1.value.applyQty = ''
form1.value.deliveryQty = ''
locationList.value = [];
})
}
function blur1() {
if (form1.value.itemNumber) {
getSparePartsInfo()
}
}
//
function handelScanMsg1() {
getSparePartsInfo()
}
onLoad(async(option) => {
// if (option.id) this.form.id = option.id;
// if (option.number) this.form.number = option.number;
if (option.data && JSON.parse(decodeURIComponent(option.data)) && JSON.parse(decodeURIComponent(option
.data)).id) {
let formData = JSON.parse(decodeURIComponent(option.data))
form.value.supplierName = formData.supplierName
form.value.number = formData.number
form.value.id =formData.id
}
await getInLocationDetail()
})
</script>
<style lang="scss" scoped>
.add-form-container {
min-height: calc(100vh - 140rpx);
background: white;
padding: 0px 0rpx 140rpx;
}
.u-form-item {
padding: 20rpx 30rpx;
}
.disabled {
background: #f5f5f5;
}
.footer {
position: fixed;
bottom: 0px;
left: 0px;
width: 100%;
z-index: 22;
}
.btns {
display: flex;
button {
flex: 1;
}
.sure {
background: #409eff;
color: white;
border-radius: 0px;
&::after {
border: 1px solid #409eff;
border-radius: 0px;
}
}
.reset {
background: #F5F5F5;
border-radius: 0px;
&::after {
border-radius: 0px;
}
}
}
.right-button {
background: #409eff;
color: white;
padding: 0rpx 30rpx;
border-radius: 16rpx;
text-align: center;
font-size: 28rpx;
}
.select {
display: flex;
align-items: center;
height: 72rpx;
width: 100%;
.input {
flex: 1;
font-size: 28rpx;
color: #000000;
}
.placeholder {
flex: 1;
font-size: 28rpx;
color: rgb(192, 196, 204);
}
}
.title {
padding: 32rpx 0rpx;
position: relative;
span {
position: absolute;
left: -16rpx;
color: #fa3534;
top: 19px;
}
}
.list {
padding: 0rpx 30rpx;
.item {
display: flex;
margin-bottom: 20rpx;
.item-box {
background: #F5F5F5;
border-radius: 12rpx;
flex: 1;
width: 0rpx;
}
.spare-title {
padding: 20rpx 30rpx;
border-bottom: 1px solid #e4e4e4;
.title-txt {
color: #409eff;
font-size: 30rpx;
font-weight: bold;
}
}
.dec {
color: #9c9c9c;
padding: 20rpx 30rpx 20rpx;
}
}
}
.add-btn {
display: flex;
justify-content: flex-start;
align-items: center;
}
.popup-title {
text-align: center;
font-size: 32rpx;
font-weight: bold;
color: #409eff;
padding: 30rpx 30rpx 0px
}
.popup {
width: 600rpx;
padding: 30rpx 0rpx 30rpx;
}
.popup-footer {
display: flex;
border-top: 1px solid #e4e4e4;
view {
line-height: 100rpx;
flex: 1;
text-align: center;
&.sure {
color: #409eff;
}
}
}
::v-deep .u-checkbox-group {
display: grid !important;
}
</style>

148
src/pages/inLocation/index.vue

@ -0,0 +1,148 @@
<template>
<!-- 采购入库 -->
<view class="container">
<u-navbar back-icon-color='#fff' :background="{ background: '#409eff'}" back-text="" title-color='#fff'
title="采购入库">
</u-navbar>
<!-- <Search @search='search' @screen='screen' /> -->
<view class="list">
<view class="item" v-for="(item,index) in list" :key="index" @click="openDetail(item)">
<view class="title">
<view class="title-txt">
{{item.number}}
</view>
<view class="time">
{{`${$time.formatDate(item.createTime)}`}}
</view>
</view>
<view class="dec">
采购人:<span>{{item.purchaser}}</span>
</view>
<view class="dec" v-if="item.date&&item.date.length>0">
采购时间:<span>{{`${item.date[0]}-${item.date[1]>=10?item.date[1]:'0'+item.date[1]}-${item.date[2]>=10?item.date[2]:'0'+item.date[2]}`}}</span>
</view>
<view class="bottom">
<view class="status">
<u-tag text="未完成" v-if="item.status=='INCOMPLETE'" bg-color='rgba(255,255,255,0)' color='#e01f54'
border-color='#e01f54' type="success" shape='circle' />
<u-tag text="已完成" v-else-if="item.status=='COMPLETE'" bg-color='rgba(255,255,255,0)' color='#2ba471'
border-color='#2ba471' type="info" shape='circle' />
</view>
</view>
</view>
</view>
<view style="height: constant(safe-area-inset-bottom); height: env(safe-area-inset-bottom);"></view>
</view>
</template>
<script setup lang="ts">
import {
onLoad,
onShow,
onReachBottom
} from '@dcloudio/uni-app'
import {
ref,
getCurrentInstance
} from 'vue'
import * as inLocationApi from "@/api/inLocation"
const { proxy } = getCurrentInstance()
const params = ref({
pageNo: 1,
pageSize: 10,
})
const status = ref('loadmore') //
const list = ref([])
function openDetail(item){
if(!proxy.$auth.hasPermiOr(['eam:item-order-main:inOperation']))return;
proxy.$tab.navigateTo(`/pages/inLocation/addForm?data=${encodeURIComponent(JSON.stringify(item))}`)
}
async function getList() {
if (status.value == 'nomore') return;
status.value = 'loading';
proxy.$modal.loading('加载中')
await inLocationApi.getInLocationPage(params.value).then((res) => {
proxy.$modal.closeLoading()
if (res.data.list.length > 0) {
list.value = list.value.concat(res.data.list);
params.value.pageNo++;
status.value = 'loadmore'
} else {
status.value = 'nomore'
}
}).catch(() => { })
}
onLoad((option) => {
if (option.type) params.value.type = option.type;
})
onShow(() => {
params.value.pageNo = 1
list.value = []
status.value = 'loadmore'
getList()
})
onReachBottom(() => {
getList()
})
</script>
<style lang="scss" scoped>
.container{
background: #f5f5f5;
min-height: 100vh;
}
.list {
background: #f5f5f5;
margin-top: 20rpx;
.item {
padding: 30rpx 30rpx 0px 30rpx;
margin-top: 20rpx;
background: white;
position: relative;
.title {
display: flex;
align-items: center;
padding-bottom: 20rpx;
.title-txt {
color: #409eff;
font-weight: bold;
font-size: 36rpx;
width: 0px;
flex: 1;
}
.time {
color: #919191;
}
}
.dec {
padding-bottom: 20rpx;
span {
color: #999999;
}
}
.last {
padding-bottom: 30rpx;
}
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #E4E4E4;
padding: 20rpx 0px;
height: 90rpx;
}
}
}
</style>

274
src/pages/index.vue

@ -0,0 +1,274 @@
<template>
<view class="index-content">
<u-navbar back-icon-color='#fff' back-icon-name=''
:background="{ background: 'rgba(64, 158,255,'+bgOpacity+')'}" back-text="" title-color='#fff'
:immersive='true' :border-bottom='false' title="首页">
</u-navbar>
<view class="top">
<image src="../static/images/mobile_bg.png" class="bg" mode=""></image>
<view class="top-box" v-if="getAccessToken()">
<view class="info">
<image :src="store.avatar" class="cu-avatar" mode="" v-if="store.avatar"></image>
<view class="cu-avatar" v-else>
<u-icon name="account-fill" color="#ababab" size="100"></u-icon>
</view>
<view class="user-info">
<view class="name">{{store.name}}
<!-- <span v-if="store.post">{{store.post.name}}</span> -->
</view>
<!-- <view class="tips">{{store.dept.name}}</view> -->
</view>
</view>
</view>
<view class="top-box" v-else>
<view class="info">
<view class="cu-avatar">
<u-icon name="account-fill" color="#ababab" size="100"></u-icon>
</view>
<view class="user-info" @click="handleLogin">
<view class="name">点击登录</view>
</view>
</view>
</view>
</view>
<view class="box">
<view class="" v-for="(item,index) in meaus" :key='index'>
<view class="title">{{item.name}}</view>
<u-row gutter="16" style="padding:0px 20rpx ;">
<u-col span="3" v-for="(cur,key) in item.children" :key='key'>
<view class="icon-item" @click="open(cur.path)">
<!-- 扫码图标 -->
<image src="../static/images/icon8.png" mode="" v-if="cur.componentName == 'scanCodeMeau'"></image>
<!-- 采购入库图标 -->
<image src="../static/images/icon1.png" mode="" v-else-if="cur.componentName == 'inLocation'"></image>
<!-- 备件归还图标 -->
<image src="../static/images/icon3.png" mode="" v-else-if="cur.componentName == 'sparePartsReturn'"></image>
<!-- 采购出库图标 -->
<image src="../static/images/icon2.png" mode="" v-else-if="cur.componentName == 'outLocation'"></image>
<view>{{cur.name}}</view>
</view>
</u-col>
</u-row>
</view>
<!-- <view class="">
<view class="title">扫码</view>
<u-row gutter="16" style="padding:0px 20rpx ;">
<u-col span="3">
<view class="icon-item" @click="open('/pages/scanCode/scanCode')">
<image src="../static/images/icon8.png" mode=""></image>
<view>扫码</view>
</view>
</u-col>
</u-row>
</view> -->
<!-- <view class="" v-if="menus1&&menus1.length>0">
<view class="title">采购入库</view>
<u-row gutter="16" style="padding:0px 20rpx ;">
<block v-for="(item,index) in menus1" :key="index">
<u-col span="3" v-if="item.path == 'purchaseIn'">
<view class="icon-item" @click="open('/pages/inLocation/index')">
<image src="../static/images/icon1.png" mode=""></image>
<view>{{item.name}}</view>
</view>
</u-col>
<u-col span="3" v-else-if="item.path == 'itemIn'">
<view class="icon-item" @click="open('/pages/sparePartsReturn/addForm')">
<image src="../static/images/icon3.png" mode=""></image>
<view>{{item.name}}</view>
</view>
</u-col>
</block>
</u-row>
</view>
<view class="" v-if="menus2&&menus2.length>0">
<view class="title">出库</view>
<u-row gutter="16">
<block v-for="(item,index) in menus2" :key="index">
<u-col span="3" v-if="item.path == 'itemOut'">
<view class="icon-item" @click="open('/pages/outLocation/index')">
<image src="../static/images/icon2.png" mode=""></image>
<view>{{item.name}}</view>
</view>
</u-col>
</block>
</u-row>
</view> -->
</view>
<view class="btn" @click="handleLogout" v-if="getAccessToken()">退出登录</view>
</view>
</template>
<script setup lang="ts">
import {
onPageScroll,
onLoad
} from '@dcloudio/uni-app'
import {
ref,
getCurrentInstance
} from 'vue'
import {
getAccessToken
} from '@/utils/auth'
import { useCountStore } from '@/store'
const { proxy } = getCurrentInstance()
// store
const store = useCountStore()
const bgOpacity = ref(0)
const meaus = ref([])
// const menus2 = ref([])
function open(url) {
if (!getAccessToken()) {
proxy.$tab.navigateTo('/pages/login')
return
}
proxy.$tab.navigateTo("/" + url)
}
function handleLogout() {
proxy.$modal.confirm('确定注销并退出系统吗?').then(() => {
store.LogOut().then(() => {
proxy.$tab.reLaunch('/pages/login')
}).catch(() => { })
}).catch(() => { })
}
function handleLogin() {
proxy.$tab.navigateTo('/pages/login')
}
onLoad(async () => {
await proxy.$onLaunched;
// menus1.value = store.menus1
// menus2.value = store.menus2
meaus.value = store.meaus
console.log(meaus.value )
})
onPageScroll((e) => {
if (e.scrollTop > 0) {
bgOpacity.value = e.scrollTop / 200;
} else {
bgOpacity.value = 0
}
})
</script>
<style scoped lang="scss">
.index-content {
background-color: white;
min-height: 100vh;
padding-bottom: 20rpx;
}
.bg {
width: 100%;
}
.top {
position: relative;
image {
height: calc(var(--status-bar-height) + 310rpx);
}
}
.info {
position: absolute;
top: calc(var(--status-bar-height) + 110rpx);
left: 80rpx;
right: 80rpx;
display: flex;
align-items: center;
.cu-avatar {
border: 4rpx solid #eaeaea;
width: 140rpx;
height: 140rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: white;
.icon {
font-size: 80rpx;
color: #f5f5f5;
}
}
.user-info {
margin-left: 30rpx;
flex: 1;
.name {
line-height: 60rpx;
font-size: 36rpx;
font-weight: bold;
line-height: 60rpx;
margin-right: 20rpx;
color: white;
span {
font-weight: normal;
font-size: 28rpx;
padding-left: 20rpx;
}
}
.tips {
padding: 10rpx 20rpx;
background: #3952ae;
color: white;
border-radius: 50rpx;
font-size: 24rpx;
display: inline-block;
}
}
}
.box {
.title {
font-size: 32rpx;
font-weight: bold;
padding: 50rpx 50rpx 30rpx;
}
.icon-item {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
margin: 20rpx 0px;
image {
width: 80rpx;
height: 80rpx;
}
view {
margin-top: 20rpx;
color: #999999;
}
}
}
.btn {
width: calc(100vw - 60rpx);
margin: 30rpx auto;
background-color: rgb(64, 158, 255);
color: #FFFFFF;
height: 90rpx;
line-height: 90rpx;
text-align: center;
border-radius: 10rpx;
font-size: 32rpx;
}
</style>

232
src/pages/login.vue

@ -0,0 +1,232 @@
<template>
<view class="normal-login-container">
<view class="logo-img">
<u-icon name="close" size="40" class="icon" @click="$tab.reLaunch('/pages/index')"></u-icon>
<view class="logo-title">
<view>智慧设备管理综合系统</view>
<view>让设备管理更智能更高效</view>
</view>
<image src="../static/images/banner/logo-banner.png" mode="widthFix"></image>
</view>
<view class="box">
<view class="box-shadow">
</view>
<view class="logo-content">
<text class="title">您好欢迎登录</text>
</view>
<view class="login-form-content">
<view class="input-item-label">登录账号</view>
<view class="input-item flex align-center">
<input v-model="loginForm.username" class="input" type="text" placeholder="请输入账号" maxlength="30"
style="height: 100%;" />
</view>
<view class="input-item-label">登录密码</view>
<view class="input-item flex align-center">
<input v-model="loginForm.password" type="password" class="input" placeholder="请输入密码" maxlength="20"
style="height: 100%;" />
</view>
<view class="action-btn">
<button @click="handleLogin" class="login-btn cu-btn block bg-blue lg ">登录</button>
</view>
</view>
<view class="xieyi text-center">
<text class="text-grey1">登录即代表同意</text>
<text @click="handleUserAgrement" class="text-blue">用户协议</text>
<text @click="handlePrivacy" class="text-blue">隐私协议</text>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import * as loginApi from "@/api/login"
import {
ref,
getCurrentInstance
} from 'vue'
const { proxy } = getCurrentInstance()
let loginForm = ref({
tenantName: "闻荫源码",
username: "",
password: "",
captchaVerification: "",
rememberMe: false,
code: '1',
uuid: "APP"
})
import { storeToRefs } from 'pinia'
import { useCountStore } from '@/store'
// store
const store = useCountStore()
if( import.meta.env.VITE_USER_NODE_ENV == 'development'){
loginForm.value = {
tenantName: "闻荫源码",
username: "admin",
password: "123456",
captchaVerification: "",
rememberMe: false,
code: '1',
uuid: "APP",
cid:uni.getStorageSync('cid')
}
}
async function handleLogin(params) {
if (loginForm.value.username === "") {
proxy.$modal.msgError("请输入您的账号")
} else if (loginForm.value.password === "") {
proxy.$modal.msgError("请输入您的密码")
} else {
await pwdLogin()
}
}
async function pwdLogin() {
proxy.$modal.loading("登录中,请耐心等待...")
//
store.Login(loginForm.value).then(async (res) => {
proxy.$modal.closeLoading()
await loginSuccess()
}).catch(() => { })
}
//
async function loginSuccess(result) {
await store.GetPermissionInfo().then(res => {
}).catch(() => {})
await store.GetInfo().then(res => {
proxy.$tab.reLaunch('/pages/index')
}).catch(() => {})
}
</script>
<style lang="scss" scoped>
page {
background-color: #ffffff;
}
.normal-login-container {
width: 100%;
.logo-content {
width: 100%;
font-size: 40rpx;
padding: 50rpx 80rpx 0rpx;
.title {
font-weight: bold;
color: #000000;
}
}
.box {
position: relative;
}
.box-shadow {
box-shadow: 0px -10rpx 16rpx rgba(64, 158, 254, 0.5);
width: 100%;
position: absolute;
height: 30rpx;
border-radius: 30rpx 30rpx 0px 0px;
}
.logo-img {
background-color: #fafcff;
height: calc(var(--status-bar-height) + 400rpx);
position: relative;
.icon {
position: absolute;
top: calc(var(--status-bar-height) + 20rpx);
left: 40rpx;
}
.logo-title {
position: absolute;
left: 50rpx;
top: calc(var(--status-bar-height) + 80rpx);
z-index: 11;
view {
&:nth-child(1) {
color: #409eff;
font-weight: bold;
font-size: 36rpx;
}
&:nth-child(2) {
color: #999999;
font-size: 24rpx;
}
}
}
image {
width: 75%;
display: block;
position: absolute;
bottom: 0px;
right: 0px;
}
}
.login-form-content {
margin: 40rpx auto;
width: 80%;
.input-item-label {
font-size: 30rpx;
// font-weight: bold;
color: #888888;
}
.input-item {
margin: 20rpx auto 40rpx;
border: 1px solid #E4E4E4;
padding: 0px 20rpx;
height: 90rpx;
.icon {
font-size: 38rpx;
margin-left: 20rpx;
color: #999;
}
.input {
width: 100%;
font-size: 28rpx;
line-height: 40rpx;
text-align: left;
}
}
.login-btn {
margin-top: 80rpx;
height: 80rpx;
background: #409eff;
color: white;
}
}
.xieyi {
color: #333;
margin-top: 40rpx;
font-size: 24rpx;
}
.easyinput {
width: 100%;
}
}
.login-code-img {
height: 90rpx;
}
</style>

531
src/pages/outLocation/addForm.vue

@ -0,0 +1,531 @@
<template>
<!-- 添加维修工单 -->
<view class="add-form-container">
<u-form :model="form" ref="formRef" label-width="160rpx">
<u-form-item label="申请人" prop="applyName" required class='disabled'>
<u-input v-model="form.applyName" placeholder="请输入申请人" disabled />
</u-form-item>
<u-form-item label="申请部门" prop="applyDeptName" required class='disabled'>
<u-input v-model="form.applyDeptName" placeholder="请输入申请部门" disabled />
</u-form-item>
<u-form-item label="审批人" prop="approveName" required class='disabled'>
<u-input v-model="form.approveName" placeholder="请输入审批人" disabled />
</u-form-item>
</u-form>
<view class="list">
<view class="title">
<span>*</span>申领信息
</view>
<view class="item " v-for="(item,index) in form.subList" :key="index">
<view class="item-box">
<view class="spare-title">
<view class="title-txt">
备件名称{{item.itemName}}
</view>
</view>
<u-row gutter="16">
<!-- <u-col :span="24">
<view class="dec">
库位{{item.locationNumber}}
</view>
</u-col> -->
<u-col :span="24">
<view class="dec">
已出库数量:{{item.receiveQty}}
</view>
</u-col>
<u-col :span="24">
<view class="dec">
申请数量:{{item.qty}}
</view>
</u-col>
</u-row>
</view>
</view>
</view>
<view class="list">
<view class="title">
<span>*</span>出库信息
</view>
<view class="item " v-for="(item,index) in form.itemNumbers" :key="index">
<view class="item-box">
<view class="spare-title">
<view class="title-txt">
备件名称{{item.itemName}}
</view>
</view>
<u-row gutter="16">
<u-col :span="24">
<view class="dec">
出库数量{{item.qty}}
</view>
</u-col>
<u-col :span="24">
<view class="dec">
申请数量{{item.applyQty}}
</view>
</u-col>
<u-col :span="24">
<view class="dec">
库位编码{{item.locationNumber}}
</view>
</u-col>
<!-- <u-col :span="24">
<view class="dec">
库位名称{{item.locationName}}
</view>
</u-col> -->
<u-col :span="24">
<view class="dec">
库位类型{{item.isInAccount == 'FALSE'?'帐外库' :'帐内库'}}
</view>
</u-col>
</u-row>
</view>
<u-icon name="minus-circle" color="#aaaaaa" size="60" @click="delSpareParts(item,index)"></u-icon>
</view>
<view class="add-btn">
<u-button type="primary" @click="open"><u-icon name="plus-circle" color="#ffffff"
size="36"></u-icon>添加备件</u-button>
</view>
</view>
<view class="footer">
<view class="btns">
<button class="reset" @click="reset">重置</button>
<button class="sure" @click="submit" :loading='loading' :disabled='loading'>确定</button>
</view>
<view style="height: constant(safe-area-inset-bottom); height: env(safe-area-inset-bottom);"></view>
</view>
<!-- 添加备件 -->
<u-popup v-model="isPopupShow" mode="center" border-radius="14">
<view class="popup-title">添加备件</view>
<scroll-view scroll-y="true" style="max-height:60vh;">
<view class="popup">
<u-form :model="form1" ref="form1Ref" label-width="180rpx">
<u-form-item label="库位" prop="locationNumber" required>
<u-input v-model="form1.locationNumber" placeholder="请输入库位" @blur="blur()"
@confirm="handelScanMsg" :focus='isFocus' />
</u-form-item>
<u-form-item :label="`备件名称`" prop="itemNumber" required class="disabled">
<view class="select">
<u-input v-model="form1.itemName" placeholder="请选择备件" disabled />
</view>
</u-form-item>
<u-form-item label="申请数量" prop="applyQty" required class="disabled">
<u-input v-model="form1.applyQty" type="number" disabled placeholder="请输入申请数量" />
</u-form-item>
<u-form-item label="已出库数量" prop="receiveQty" required class="disabled">
<u-input v-model="form1.receiveQty" type="number" disabled placeholder="请输入已出库数量" />
</u-form-item>
<u-form-item label="库存数量" prop="stockQty" required class="disabled">
<u-input v-model="form1.stockQty" type="number" disabled placeholder="请输入库存数量" />
</u-form-item>
<u-form-item label="剩余出库数量" prop="totalReception" required class="disabled">
<u-input v-model="form1.totalReception" type="number" disabled placeholder="请输入出库数量" />
</u-form-item>
<u-form-item label="出库数量" prop="qty" required>
<u-input v-model="form1.qty" type="number" placeholder="请输入出库数量" />
</u-form-item>
<u-form-item label="描述" prop="describes">
<u-input v-model="form1.describes" placeholder="请输入描述" />
</u-form-item>
</u-form>
</view>
</scroll-view>
<view class="popup-footer">
<view @click="isPopupShow = false">取消</view>
<view class="sure" @click="addSpare">确认</view>
</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
import {
onLoad
} from '@dcloudio/uni-app'
import {
ref,
getCurrentInstance
} from 'vue'
import * as outLocationApi from "@/api/outLocation"
import * as locationApi from "@/api/location"
const { proxy } = getCurrentInstance()
const loading = ref(false)
const orderList = ref([])//
//
const isPopupShow = ref(false)
const form = ref({
id: '',
number: '',
supplierName: '',
itemNumbers: [],
subList: []
})
const form1 = ref({
itemNumber: "",
itemName: '',
locationNumber: '',
applyQty: '',
receiveQty: '',
stockQty: '',
totalReception:'',
qty: ''
})
const isShow = ref(false)
const isInAccount = ref('FALSE')
const isFocus = ref(false)
const msg = ref('')
//
function submit() {
if (form.value.itemNumbers.length === 0) {
proxy.$modal.showToast('请添加出库信息')
return;
}
proxy.$modal.confirm('是否添加出库信息').then(() => {
proxy.$modal.loading('加载中')
loading.value = true
outLocationApi.outLocationCreat(form.value).then((res) => {
proxy.$modal.closeLoading()
if (res.data) {
proxy.$modal.showToast('添加成功')
setTimeout(() => {
proxy.$tab.navigateBack()
loading.value = false
}, 1500)
} else {
proxy.$modal.showToast('添加失败')
loading.value = false
}
}).catch(() => {
proxy.$modal.closeLoading()
loading.value = false
})
})
}
//
function reset() {
form.value.itemNumbers = []
}
//
async function getInLocationDetail() {
// let itemNumbers = form.value.itemNumbers.map(item=>{
// return {
// itemNumber:item.itemNumber,
// qty:item.qty,
// locationNumber:item.locationNumber,
// }
// })
await outLocationApi.getOutLocationDetail({
id: form.value.id,
number: form.value.number,
// itemNumbers:itemNumbers || []
}).then(res => {
form.value.applyName = res.data.applyName
form.value.approveName = res.data.approveName
form.value.applyDeptName = res.data.applyDeptName
form.value.subList = res.data.subList
}).catch(() => { })
}
//
function open() {
form1.value = {
itemNumber: "",
itemName: '',
locationNumber: '',
applyQty: '',
receiveQty: '',
stockQty: '',
qty: ''
}
isPopupShow.value = true
isShow.value = false
isFocus.value = true
}
//
function addSpare() {
//
if (!form1.value.locationNumber) {
proxy.$modal.showToast('请选择库位')
return;
}
if (!form1.value.itemNumber) {
proxy.$modal.showToast(msg.value)
return;
}
if (!form1.value.qty) {
proxy.$modal.showToast(`请输入数量`)
return;
}
if (Number(form1.value.qty) + Number(form1.value.receiveQty) > Number(form1.value.applyQty)) {
proxy.$modal.showToast('已出库数量和出库数量不可大于申请数量')
return;
}
if (Number(form1.value.qty) > Number(form1.value.totalReception)) {
proxy.$modal.showToast('出库数量不可大于剩余出库数量')
return;
}
if (form.value.itemNumbers && form.value.itemNumbers.length > 0) {
let arr = form.value.itemNumbers.filter(item => item.locationNumber == form1.value.locationNumber)
if (arr && arr.length > 0) {
proxy.$modal.showToast('该库位已添加')
return;
}
let arr1 = form.value.subList.filter(item => item.itemNumber == form1.value.itemNumber)
if (!arr1 || (arr1 && arr1.length == 0)) {
proxy.$modal.showToast('申领信息没有该备件')
return;
}
}
form.value.itemNumbers.push(form1.value)
isPopupShow.value = false
}
//
function delSpareParts(item,index) {
let bol = form.value.itemNumbers.some(cur=>cur.itemNumber == item.itemNumber&&item.isInAccount == 'FALSE'&&cur.isInAccount == 'TRUE')
if(bol){
proxy.$modal.showToast('请先删除该备件得帐内库')
return;
}
form.value.itemNumbers.splice(index, 1)
}
function getLocation() {
let itemNumbers = form.value.itemNumbers.map(item=>{
return {
itemNumber:item.itemNumber,
qty:item.qty,
locationNumber:item.locationNumber,
}
})
locationApi.getOutLocation({
number: form1.value.locationNumber,
id: form.value.id,
itemNumbers:itemNumbers
}).then(res => {
if (!res.data) {
msg.value = res.msg
form1.value.areaNumber = '';
form1.value.itemName = '';
form1.value.itemNumber = '';
form1.value.receiveQty ='';
form1.value.applyQty ='';
form1.value.stockQty = '';
form1.value.totalReception ='';
form1.value.isInAccount ='';
isInAccount.value ='';
return;
}
form1.value.areaNumber = res.data.areaNumber;
form1.value.itemName = res.data.itemName;
form1.value.itemNumber = res.data.itemNumber;
form1.value.receiveQty = res.data.receiveQty || 0;
form1.value.applyQty = res.data.applyQty || 0;
form1.value.stockQty = res.data.qty || 0;
form1.value.totalReception = res.data.totalReception || 0;
form1.value.isInAccount = res.data.isInAccount;
isInAccount.value = res.data.isInAccount || ''
// this.itemNumber = res.data.itemNumber || ''
}).catch((error) => {
msg.value = error.msg
form1.value.areaNumber = '';
form1.value.itemName = '';
form1.value.itemNumber = '';
form1.value.receiveQty = '';
form1.value.applyQty = '';
form1.value.stockQty = '';
isInAccount.value = '';
})
}
function blur() {
if (form1.value.locationNumber) {
getLocation()
}
}
function handelScanMsg() {
getLocation()
}
onLoad(async (option) => {
if (option.data && JSON.parse(decodeURIComponent(option.data)) && JSON.parse(decodeURIComponent(option
.data)).id) {
let formData = JSON.parse(decodeURIComponent(option.data))
form.value.supplierName = formData.supplierName
form.value.number = formData.number
form.value.id = formData.id
}
await getInLocationDetail()
})
</script>
<style lang="scss" scoped>
.add-form-container {
min-height: calc(100vh - 140rpx);
background: white;
padding: 0px 0rpx 140rpx;
}
.u-form-item {
padding: 20rpx 30rpx;
}
.disabled {
background: #f5f5f5;
}
.footer {
position: fixed;
bottom: 0px;
left: 0px;
width: 100%;
z-index: 22;
}
.btns {
display: flex;
button {
flex: 1;
}
.sure {
background: #409eff;
color: white;
border-radius: 0px;
&::after {
border: 1px solid #409eff;
border-radius: 0px;
}
}
.reset {
background: #F5F5F5;
border-radius: 0px;
&::after {
border-radius: 0px;
}
}
}
.right-button {
background: #409eff;
color: white;
padding: 0rpx 30rpx;
border-radius: 16rpx;
text-align: center;
font-size: 28rpx;
}
.select {
display: flex;
align-items: center;
height: 72rpx;
width: 100%;
.input {
flex: 1;
font-size: 28rpx;
color: #000000;
}
.placeholder {
flex: 1;
font-size: 28rpx;
color: rgb(192, 196, 204);
}
}
.title {
padding: 32rpx 0rpx;
position: relative;
span {
position: absolute;
left: -16rpx;
color: #fa3534;
top: 19px;
}
}
.list {
padding: 0rpx 30rpx;
.item {
display: flex;
margin-bottom: 20rpx;
.item-box {
background: #F5F5F5;
border-radius: 12rpx;
flex: 1;
width: 0rpx;
}
.spare-title {
padding: 20rpx 30rpx;
border-bottom: 1px solid #e4e4e4;
.title-txt {
color: #409eff;
font-size: 30rpx;
font-weight: bold;
}
}
.dec {
color: #9c9c9c;
padding: 20rpx 30rpx 20rpx;
}
}
}
.add-btn {
display: flex;
justify-content: flex-start;
align-items: center;
}
.popup-title {
text-align: center;
font-size: 32rpx;
font-weight: bold;
color: #409eff;
padding: 30rpx 30rpx 0px
}
.popup {
width: 600rpx;
padding: 30rpx 0rpx 30rpx;
}
.popup-footer {
display: flex;
border-top: 1px solid #e4e4e4;
view {
line-height: 100rpx;
flex: 1;
text-align: center;
&.sure {
color: #409eff;
}
}
}
::v-deep .u-checkbox-group {
display: grid !important;
}
</style>

166
src/pages/outLocation/index.vue

@ -0,0 +1,166 @@
<template>
<!-- 领用入库 -->
<view class="container">
<!-- <u-navbar back-icon-color='#fff' :background="{ background: '#409eff'}" back-text="" title-color='#fff'
title="领用入库">
</u-navbar> -->
<!-- <Search @search='search' @screen='screen' /> -->
<view class="list">
<view class="item" v-for="(item,index) in list" :key="index" @click="openDetail(item)">
<view class="title">
<view class="title-txt">
{{item.number}}
</view>
<!-- <view class="time">
{{`${$time.formatDate(item.createTime)}`}}
</view> -->
</view>
<view class="dec">
申请人:<span>{{item.applyName}}</span>
</view>
<view class="dec">
申请时间:<span>{{`${$time.formatDate(item.createTime)}`}}</span>
</view>
<view class="dec">
申请部门:<span>{{item.applyDeptName}}</span>
</view>
<view class="dec">
审批人:<span>{{item.approveName}}</span>
</view>
<view class="dec">
审批时间:<span>{{`${$time.formatDate(item.approveTime)}`}}</span>
</view>
<view class="bottom">
<view class="status">
<u-tag text="待审批" v-if="item.status==0" bg-color='rgba(255,255,255,0)' color='#fe8463'
border-color='#fe8463' type="primary" shape='circle' />
<u-tag text="审批通过" v-else-if="item.status==1" bg-color='rgba(255,255,255,0)' color='#2EC7C9'
border-color='#2EC7C9' type="info" shape='circle' />
<u-tag text="审批驳回" v-else-if="item.status==2" bg-color='rgba(255,255,255,0)' color='#e01f54'
border-color='#e01f54' type="success" shape='circle' />
<u-tag text="出库中" v-else-if="item.status==3" bg-color='rgba(255,255,255,0)' color='#005eaa'
border-color='#005eaa ' type="error" shape='circle' />
<u-tag text="完成" v-else-if="item.status==4" bg-color='rgba(255,255,255,0)' color='#2ba471'
border-color='#2ba471' type="info" shape='circle' />
<u-tag text="撤单" v-else-if="item.status==5" bg-color='rgba(255,255,255,0)' color='#d7d7d7'
border-color='#d7d7d7 ' type="warning" shape='circle' />
</view>
</view>
</view>
</view>
<view style="height: constant(safe-area-inset-bottom); height: env(safe-area-inset-bottom);"></view>
</view>
</template>
<script setup lang="ts">
import {
onLoad,
onShow,
onReachBottom
} from '@dcloudio/uni-app'
import {
ref,
getCurrentInstance
} from 'vue'
import * as outLocationApi from "@/api/outLocation"
import auth from '@/plugins/auth'
const { proxy } = getCurrentInstance()
const params = ref({
pageNo: 1,
pageSize: 10,
})
const status = ref('loadmore') //
const list = ref([])
function openDetail(item){
if(!proxy.$auth.hasPermiOr(['eam:item-apply-record-main:outOperation']))return;
proxy.$tab.navigateTo(`/pages/outLocation/addForm?data=${encodeURIComponent(JSON.stringify(item))}`)
}
async function getList() {
if (status.value == 'nomore') return;
status.value = 'loading';
proxy.$modal.loading('加载中')
await outLocationApi.getOutLocationPage(params.value).then((res) => {
proxy.$modal.closeLoading()
if (res.data.list.length > 0) {
list.value = list.value.concat(res.data.list);
params.value.pageNo++;
status.value = 'loadmore'
} else {
status.value = 'nomore'
}
}).catch(() => { })
}
onLoad((option) => {
if (option.type) params.value.type = option.type;
})
onShow(() => {
params.value.pageNo = 1
list.value = []
status.value = 'loadmore'
getList()
})
onReachBottom(() => {
getList()
})
</script>
<style lang="scss" scoped>
.container{
background: #f5f5f5;
min-height: 100vh;
}
.list {
background: #f5f5f5;
margin-top: 20rpx;
.item {
padding: 30rpx 30rpx 0px 30rpx;
margin-top: 20rpx;
background: white;
position: relative;
.title {
display: flex;
align-items: center;
padding-bottom: 20rpx;
.title-txt {
color: #409eff;
font-weight: bold;
font-size: 36rpx;
width: 0px;
flex: 1;
}
.time {
color: #919191;
}
}
.dec {
padding-bottom: 20rpx;
span {
color: #999999;
}
}
.last {
padding-bottom: 30rpx;
}
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #E4E4E4;
padding: 20rpx 0px;
height: 90rpx;
}
}
}
</style>

188
src/pages/scanCode/scanCode.vue

@ -0,0 +1,188 @@
<template>
<!-- 添加维修工单 -->
<view class="add-form-container">
<view class="screen-input">
<u-search v-model='number' :show-action='false' :bg-color="'white'" :border-color="'#E4E4E4'"
:shape="'square'" :height="80" :placeholder="'请扫描设备或者库位'" :clearabled="true" @blur="blur()"
@confirm="handelScanMsg">
</u-search>
</view>
<view class="title">
<view class="">
详细信息
</view>
</view>
<view class="list">
<view class="item " v-for="(item,index) in list" :key="index">
<view class="item-box">
<view class="spare-title">
<view class="title-txt">
库位名称:{{item.name}}
</view>
</view>
<view class="dec">
<view>库位编码</view>
<view>{{item.locationNumber}}</view>
</view>
<view class="dec">
<view>库位名称</view>
<view>{{item.name}}</view>
</view>
<view class="dec">
<view>库区编码</view>
<view>{{item.areaNumber}}</view>
</view>
<view class="dec">
<view>库区名称</view>
<view>{{item.areaName}}</view>
</view>
<view class="dec">
<view>库位类型</view>
<view>{{item.isInAccount == 'TRUE'?'帐内库' :'帐外库'}}</view>
</view>
<view class="dec">
<view>设备编码</view>
<view>{{item.itemNumber}}</view>
</view>
<view class="dec">
<view>设备名称</view>
<view>{{item.itemName}}</view>
</view>
<view class="dec">
<view>库存</view>
<view>{{item.qty}}</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import {
onLoad
} from '@dcloudio/uni-app'
import {
ref,
getCurrentInstance
} from 'vue'
import * as locationApi from "@/api/location"
const { proxy } = getCurrentInstance()
const number = ref('LN0000000001')
const list = ref([])
function getPdaItemAndLocation() {
locationApi.pdaItemAndLocation(number.value).then((res) => {
if(!res.data||res.data.length==0){
list.value = []
if(res.msg){
proxy.$modal.showToast(res.msg)
}
return;
}
list.value = res.data
}).catch((err)=>{
list.value = []
proxy.$modal.showToast(err.msg)
})
}
function blur() {
if (number.value) {
getPdaItemAndLocation()
}
}
//
function handelScanMsg() {
getPdaItemAndLocation()
}
onLoad(async (option) => {
getPdaItemAndLocation()
})
</script>
<style lang="scss" scoped>
.add-form-container {
min-height: 100vh;
background: white;
}
.u-form-item {
padding: 20rpx 30rpx;
}
.screen-input {
margin: 30rpx;
}
.title {
display: flex;
align-items: center;
padding: 0px 30rpx;
// background: #f5f5f5;
margin-top: 10px;
font-weight: bold;
font-size: 32rpx;
view {
&:nth-child(1) {
flex: 1;
border-left: 10rpx solid #409eff;
padding-left: 20rpx;
font-weight: bold;
color: #409eff;
}
}
}
.list {
padding: 30rpx;
.item {
display: flex;
margin-bottom: 20rpx;
.item-box {
background: #F5F5F5;
border-radius: 12rpx;
flex: 1;
width: 0rpx;
}
.spare-title {
padding: 20rpx 30rpx;
border-bottom: 1px solid #e4e4e4;
.title-txt {
color: #409eff;
font-size: 30rpx;
font-weight: bold;
}
}
.dec {
color: #9c9c9c;
padding: 20rpx 30rpx 20rpx;
display: flex;
view {
&:nth-child(1) {
width: 150rpx;
}
&:nth-child(2) {
flex: 1;
word-wrap: break-word;
width: 0px;
}
}
}
}
}
</style>

530
src/pages/sparePartsReturn/addForm.vue

@ -0,0 +1,530 @@
<template>
<!-- 添加维修工单 -->
<view class="add-form-container">
<u-form :model="form" ref="formRef" label-width="160rpx">
<!-- <u-form-item label="入库原因" prop="res" required>
<u-input v-model="form.number" placeholder="请输入入库原因" />
</u-form-item> -->
<u-form-item label="归还人员" prop="reverterName" required>
<view class="select" @click="openSingleColumn('reverterId',form.reverterId,reverterUser)">
<view class="input" v-if='form.reverterId'>
{{selectFormat(form.reverterId,reverterUser)}}
</view>
<view class="placeholder" v-else>
{{`请选择归还人员`}}
</view>
<u-icon name="arrow-right" color="#aaaaaa" size="28"></u-icon>
</view>
</u-form-item>
</u-form>
<view class="list">
<view class="title">
<span>*</span>归还备件
</view>
<view class="item " v-for="(item,index) in form.itemNumbers" :key="index">
<view class="item-box">
<view class="spare-title">
<view class="title-txt">
备件名称{{item.itemName}}
</view>
</view>
<u-row gutter="16">
<u-col :span="24">
<view class="dec">
数量{{item.qty}}
</view>
</u-col>
</u-row>
</view>
<u-icon name="minus-circle" color="#aaaaaa" size="60" @click="delSpareParts(index)"></u-icon>
</view>
<view class="add-btn">
<u-button type="primary" @click="open"><u-icon name="plus-circle" color="#ffffff"
size="36"></u-icon>添加备件</u-button>
</view>
</view>
<view class="footer">
<view class="btns">
<button class="reset" @click="reset">重置</button>
<button class="sure" @click="submit" :loading='loading' :disabled='loading'>确定</button>
</view>
<view style="height: constant(safe-area-inset-bottom); height: env(safe-area-inset-bottom);"></view>
</view>
<!-- 添加备件 -->
<u-popup v-model="isPopupShow" mode="center" border-radius="14">
<view class="popup-title">添加备件</view>
<scroll-view scroll-y="true" style="max-height:60vh;">
<view class="popup">
<u-form :model="form1" ref="form1Ref" label-width="160rpx">
<u-form-item :label="`备件编号`" prop="itemNumber" required>
<view class="select">
<u-input v-model="form1.itemNumber" placeholder="请输入备件" @blur='blur1()' @confirm="handelScanMsg1" :focus='isFocus'/>
</view>
</u-form-item>
<u-form-item :label="`备件名称`" prop="itemNumber" required class="disabled">
<view class="select">
<u-input v-model="form1.itemName" placeholder="根据备件编号获取" disabled />
</view>
</u-form-item>
<u-form-item label="库位" prop="locationNumber" required v-if="isShow">
<u-input v-model="form1.locationNumber" placeholder="请输入库位" @blur="blur()" @confirm="handelScanMsg"/>
<view class="right-button" @click="chickRightButton">
扫描
</view>
</u-form-item>
<u-form-item label="数量" prop="qty" required>
<u-input v-model="form1.qty" type="number" placeholder="请输入数量" />
</u-form-item>
<u-form-item label="描述" prop="describes" required>
<u-input v-model="form1.describes" placeholder="请输入描述" />
</u-form-item>
</u-form>
</view>
</scroll-view>
<view class="popup-footer">
<view @click="isPopupShow = false">取消</view>
<view class="sure" @click="addSpare">确认</view>
</view>
</u-popup>
<u-select v-model="singleColumnShow" mode="single-column" :default-value='singleColumnDefaultValue'
:list="singleColumnList" @confirm="chooseSingleColumn"></u-select>
</view>
</template>
<script setup lang="ts">
import {
onLoad
} from '@dcloudio/uni-app'
import {
ref,
getCurrentInstance
} from 'vue'
import * as userApi from "@/api/user"
import * as sparePartsReturnApi from "@/api/sparePartsReturn"
import * as sparePartsApi from "@/api/spareParts"
import * as locationApi from "@/api/location"
const { proxy } = getCurrentInstance()
const loading = ref(false)
//
const isPopupShow = ref(false)
const singleColumnShow = ref(false)
const singleColumnDefaultValue = ref([])
const singleColumnList = ref([])
const field = ref('')
const reverterUser = ref([])
const form = ref({
id: '',
number: '',
itemNumbers: []
})
const form1 = ref({
itemNumber: "",
itemName: '',
locationNumber: '',
qty: ''
})
const isShow = ref(false)
const locationList = ref([])//
const locationItem = ref('')//
const isFocus = ref(false)
const choosesingleColumnItem = ref()
const itemNumber = ref()
const msg = ref()
//
function submit() {
//
if (!form.value.reverterId) {
proxy.$modal.showToast('请选择归还人员')
return;
}
if (form.value.itemNumbers.length === 0) {
proxy.$modal.showToast('请选择备件')
return;
}
proxy.$modal.confirm('是否归还备件').then(() => {
proxy.$modal.loading('加载中')
loading.value = true
sparePartsReturnApi.sparePartsReturn(form.value).then((res) => {
proxy.$modal.closeLoading()
if (res.data) {
proxy.$modal.showToast('归还成功')
setTimeout(() => {
proxy.$tab.navigateBack()
loading.value = false
}, 1500)
} else {
proxy.$modal.showToast('归还失败')
loading.value = false
}
}).catch(() => {
proxy.$modal.closeLoading()
loading.value = false
})
})
}
//
function reset() {
if (form.value.id) {
form.value.reverterId = '';
form.value.itemNumbers = []
} else {
form.value.reverterId = '';
form.value.itemNumbers = []
}
}
function selectFormat(val, array) {
let str = array.filter(item => item.value == val)[0].label
return str
}
//
function openSingleColumn(fieldName, val, list) {
singleColumnList.value = list
field.value = fieldName
if (val) {
singleColumnDefaultValue.value = [list.findIndex(item => item.value == val)]
} else {
singleColumnDefaultValue.value = []
}
singleColumnShow.value = true
}
//
function chooseSingleColumn(e) {
form.value[field.value] = e[0].value
if(field.value == 'reverterId'){
choosesingleColumnItem.value = singleColumnList.value.filter(item => item.id == e[0].value)
form.value.reverterName = choosesingleColumnItem.value[0].name
}
singleColumnShow.value = false
}
//
async function getReverterUser() {
await userApi.getReverterUser().then(res => {
res.data.map(item => {
item.value = item.id
item.label = item.nickname
})
reverterUser.value = res.data
})
}
//
function open() {
form1.value = {
itemNumber: "",
itemName: '',
locationNumber: '',
qty: ''
}
isPopupShow.value = true
isShow.value= false
isFocus.value = true
}
//
function addSpare() {
//
if (!form1.value.itemNumber) {
proxy.$modal.showToast('请选择备件')
return;
}
if (!form1.value.itemName) {
proxy.$modal.showToast(msg.value)
return;
}
if (!form1.value.locationNumber) {
proxy.$modal.showToast('请选择库位')
return;
}
if (!locationItem.value || locationItem.value.isInAccount === 'TRUE') {
proxy.$modal.showToast('该库位属于帐内库,请选择帐外库')
return;
}
if (itemNumber.value) {
proxy.$modal.showToast('该库位已绑定过其他备件')
return;
}
if (!form1.value.qty) {
proxy.$modal.showToast(`请输入数量`)
return;
}
if (!form1.value.describes) {
proxy.$modal.showToast(`请输入描述`)
return;
}
if (form.value.itemNumbers && form.value.itemNumbers.length > 0) {
let arr =form.value.itemNumbers.filter(item => item.itemNumber == form1.value.itemNumber)
if (arr && arr.length > 0) {
proxy.$modal.showToast('该备件已添加')
return;
}
}
form.value.itemNumbers.push(form1.value)
isPopupShow.value = false
}
//
function delSpareParts(index) {
form.value.itemNumbers.splice(index, 1)
}
function getLocation() {
locationApi.getLocation(form1.value.locationNumber).then(res => {
if(!res.data){
if(res.msg){
proxy.$modal.showToast(res.msg)
msg.value = res.msg
}else{
proxy.$modal.showToast('找不到该库位')
}
return;
}
locationItem.value = res.data
form1.value.areaNumber = locationItem.value.areaNumber
//
if (form.value.itemNumbers && form.value.itemNumbers.length > 0) {
let arr = form.value.itemNumbers.filter(item => item.locationNumber == form1.value.locationNumber)
if (arr && arr.length > 0) {
itemNumber.value = 1
}else{
itemNumber.value = res.data.itemNumber || ''
}
}else{
itemNumber.value = res.data.itemNumber || ''
}
}).catch(()=>{
})
}
function blur() {
if (form1.value.locationNumber) {
getLocation()
}
}
//
function handelScanMsg() {
getLocation()
}
//
function getSparePartsInfo() {
sparePartsApi.getSparePartsReturnInfo({
number: form1.value.itemNumber,
}).then(res => {
if(!res.data){
proxy.$modal.showToast(res.msg)
msg.value = res.msg
itemNumber.value = ''
form1.value.areaNumber = ''
form1.value.locationNumber = '';
form1.value.itemName = ''
return;
}
itemNumber.value = ''
form1.value.itemName = res.data.itemName
form1.value.deliveryQty = res.data.deliveryQty
form1.value.applyQty = res.data.applyQty
//
locationItem.value = res.data.list.filter(item=>item.isInAccount==='FALSE')[0]
if(locationItem.value){
form1.value.areaNumber = locationItem.value.areaNumber
form1.value.locationNumber = locationItem.value.locationNumber
isShow.value =false
}else{
form1.value.areaNumber = ''
form1.value.locationNumber = ''
isShow.value =true
}
}).catch((err)=>{
msg.value = err.msg
itemNumber.value = ''
form1.value.areaNumber = ''
form1.value.itemName = ''
form1.value.applyQty = ''
form1.value.deliveryQty = ''
locationList.value = [];
})
}
function blur1() {
if (form1.value.itemNumber) {
getSparePartsInfo()
}
}
//
function handelScanMsg1() {
getSparePartsInfo()
}
onLoad(async(option) => {
getReverterUser()
})
</script>
<style lang="scss" scoped>
.add-form-container {
min-height: calc(100vh - 140rpx);
background: white;
padding: 0px 0rpx 140rpx;
}
.u-form-item {
padding: 20rpx 30rpx;
}
.disabled {
background: #f5f5f5;
}
.footer {
position: fixed;
bottom: 0px;
left: 0px;
width: 100%;
z-index: 22;
}
.btns {
display: flex;
button {
flex: 1;
}
.sure {
background: #409eff;
color: white;
border-radius: 0px;
&::after {
border: 1px solid #409eff;
border-radius: 0px;
}
}
.reset {
background: #F5F5F5;
border-radius: 0px;
&::after {
border-radius: 0px;
}
}
}
.right-button {
background: #409eff;
color: white;
padding: 0rpx 30rpx;
border-radius: 16rpx;
text-align: center;
font-size: 28rpx;
}
.select {
display: flex;
align-items: center;
height: 72rpx;
width: 100%;
.input {
flex: 1;
font-size: 28rpx;
color: #000000;
}
.placeholder {
flex: 1;
font-size: 28rpx;
color: rgb(192, 196, 204);
}
}
.title {
padding: 32rpx 0rpx;
position: relative;
span {
position: absolute;
left: -16rpx;
color: #fa3534;
top: 19px;
}
}
.list {
padding: 0rpx 30rpx;
.item {
display: flex;
margin-bottom: 20rpx;
.item-box {
background: #F5F5F5;
border-radius: 12rpx;
flex: 1;
width: 0rpx;
}
.spare-title {
padding: 20rpx 30rpx;
border-bottom: 1px solid #e4e4e4;
.title-txt {
color: #409eff;
font-size: 30rpx;
font-weight: bold;
}
}
.dec {
color: #9c9c9c;
padding: 20rpx 30rpx 20rpx;
}
}
}
.add-btn {
display: flex;
justify-content: flex-start;
align-items: center;
}
.popup-title {
text-align: center;
font-size: 32rpx;
font-weight: bold;
color: #409eff;
padding: 30rpx 30rpx 0px
}
.popup {
width: 600rpx;
padding: 30rpx 0rpx 30rpx;
}
.popup-footer {
display: flex;
border-top: 1px solid #e4e4e4;
view {
line-height: 100rpx;
flex: 1;
text-align: center;
&.sure {
color: #409eff;
}
}
}
::v-deep .u-checkbox-group {
display: grid !important;
}
</style>

60
src/plugins/auth.js

@ -0,0 +1,60 @@
function authPermission(permission) {
const all_permission = "*:*:*"
const permissions =uni.getStorageSync('permissionInfo')
if (permission && permission.length > 0) {
return permissions.some(v => {
return all_permission === v || v === permission
})
} else {
return false
}
}
function authRole(role) {
const super_admin = "admin"
const roles = uni.getStorageSync('roles')
if (role && role.length > 0) {
return roles.some(v => {
return super_admin === v || v === role
})
} else {
return false
}
}
export default {
// 验证用户是否具备某权限
hasPermi(permission) {
return authPermission(permission)
},
// 验证用户是否含有指定权限,只需包含其中一个
hasPermiOr(permissions) {
return permissions.some(item => {
return authPermission(item)
})
},
// 验证用户是否含有指定权限,必须全部拥有
hasPermiAnd(permissions) {
return permissions.every(item => {
return authPermission(item)
})
},
// 验证用户是否具备某角色
hasRole(role) {
return authRole(role)
},
// 验证用户是否含有指定角色,只需包含其中一个
hasRoleOr(roles) {
return roles.some(item => {
return authRole(item)
})
},
// 验证用户是否含有指定角色,必须全部拥有
hasRoleAnd(roles) {
return roles.every(item => {
return authRole(item)
})
}
}

17
src/plugins/index.js

@ -0,0 +1,17 @@
import tab from './tab'
// import auth from './auth'
import modal from './modal'
import time from './time'
export default {
install(app) {
// 页签操作
app.config.globalProperties.$tab = tab
// 认证对象
// Vue.prototype.$auth = auth
// 模态框对象
app.config.globalProperties.$modal = modal
// 时间对象
app.config.globalProperties.$time = time
}
}

73
src/plugins/modal.js

@ -0,0 +1,73 @@
export default {
// 消息提示
msg(content) {
uni.showToast({
title: content,
icon: 'none'
})
},
// 错误消息
msgError(content) {
uni.showToast({
title: content,
icon: 'error'
})
},
// 成功消息
msgSuccess(content) {
uni.showToast({
title: content,
icon: 'success'
})
},
// 隐藏消息
hideMsg(content) {
uni.hideToast()
},
// 弹出提示
alert(content) {
uni.showModal({
title: '提示',
content: content,
showCancel: false
})
},
// 确认窗体
confirm(content,confirmText,cancelText) {
return new Promise((resolve, reject) => {
uni.showModal({
title: '系统提示',
content: content,
cancelText: cancelText||'取消',
confirmText: confirmText || '确定',
success: function(res) {
if (res.confirm) {
resolve(res.confirm)
}
}
})
})
},
// 提示信息
showToast(option) {
if (typeof option === "object") {
uni.showToast(option)
} else {
uni.showToast({
title: option,
icon: "none",
duration: 2500
})
}
},
// 打开遮罩层
loading(content) {
uni.showLoading({
title: content,
})
},
// 关闭遮罩层
closeLoading() {
uni.hideLoading()
}
}

32
src/plugins/tab.js

@ -0,0 +1,32 @@
export default {
// 关闭所有页面,打开到应用内的某个页面
reLaunch(url) {
return uni.reLaunch({
url: url
})
},
// 跳转到tabBar页面,并关闭其他所有非tabBar页面
switchTab(url) {
return uni.switchTab({
url: url
})
},
// 关闭当前页面,跳转到应用内的某个页面
redirectTo(url) {
return uni.redirectTo({
url: url
})
},
// 保留当前页面,跳转到应用内的某个页面
navigateTo(url) {
return uni.navigateTo({
url: url
})
},
// 关闭当前页面,返回上一页面或多级页面
navigateBack(level) {
return uni.navigateBack({
delta:level
})
}
}

19
src/plugins/time.js

@ -0,0 +1,19 @@
export default {
formatDate(timestamp){
// 获取当前时间戳(单位:毫秒)
// var timestamp = Date.now(); // 或者传入特定的时间戳值
timestamp = timestamp ? timestamp :Date.now()
// 创建Date对象并设置时间戳
var dateObj = new Date(timestamp);
// 提取年份、月份、日期等信息
var year = dateObj.getFullYear();
var month = (dateObj.getMonth() + 1).toString().padStart(2, '0'); // 注意月份从0开始计数,所以需要加1
var day = dateObj.getDate().toString().padStart(2, '0');
var hour = dateObj.getHours().toString().padStart(2, '0');
var minutes = dateObj.getMinutes().toString().padStart(2, '0');
var seconds = dateObj.getSeconds().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}`
}
}

BIN
src/static/icon/screen.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/static/images/banner/banner01.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
src/static/images/banner/banner02.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
src/static/images/banner/banner03.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
src/static/images/banner/icon1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/static/images/banner/icon2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
src/static/images/banner/icon3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
src/static/images/banner/icon4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
src/static/images/banner/icon5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
src/static/images/banner/icon6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
src/static/images/banner/icon7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

12
src/static/images/banner/login_banner.svg

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="47px" height="66px" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient gradientUnits="userSpaceOnUse" x1="5.63807152481269" y1="62.1175381975164" x2="43.4328694937704" y2="1.76792360964131" id="LinearGradient40">
<stop id="Stop41" stop-color="#09005d" offset="0" />
<stop id="Stop42" stop-color="#1a0f91" offset="1" />
</linearGradient>
</defs>
<g transform="matrix(1 0 0 1 -97 -106 )">
<path d="M 36.7877623440973 1.59223308620249 C 37.7932710870804 0.0521044544140052 39.8698652301974 -0.408494762569467 41.450991297062 0.55588484798968 L 45.378304430887 2.95244014885682 C 46.9594304977516 3.91681975941597 47.4694711644821 5.96072878478014 46.5222527834112 7.54403859316083 L 11.8977778076482 65.9393830713469 L 0.95376235865917 59.2534975623212 C 0.0648343395002736 58.7137328549186 -0.197472289103991 57.5550379496946 0.37814503477759 56.6914144178506 L 36.7877623440973 1.59223308620249 Z " fill-rule="nonzero" fill="url(#LinearGradient40)" stroke="none" transform="matrix(1 0 0 1 97 106 )" />
</g>
</svg>

BIN
src/static/images/banner/logo-banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

6
src/static/images/banner/u2335.svg

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="37px" height="37px" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1 0 0 1 -200 -131 )">
<path d="M 1.8705291643251 26.4306710705829 C 0.0206628251877919 22.5581882283421 -0.41841050822613 18.2538299761859 0.58210085807772 14.1438156584916 C 0.733257251548091 13.5319921611116 0.91320533901281 12.9273665872301 1.12194512047189 12.3299389368472 C 1.1867264319592 12.1427929258839 1.25870566694509 11.9556469149206 1.33068490193098 11.7685009039573 C 1.69058107686042 10.8471666961379 2.12245648677576 9.95462418231291 2.6191132081784 9.11246713297802 C 2.62631113167697 9.09807128598083 2.63350905517557 9.09087336248225 2.64070697867417 9.07647751548507 C 2.66230074916992 9.04048789799212 2.67669659616711 9.01169620399777 2.69829036666286 8.97570658650483 C 2.73427998415581 8.91092527501753 2.77746752514735 8.84614396353023 2.81345714264029 8.78856057554152 C 2.91422807162054 8.62300833507397 3.10857200608242 8.55102910008808 3.28852009354714 8.59421664107961 C 3.33170763453868 8.6014145645782 3.37489517553022 8.62300833507396 3.41808271652174 8.64460210556974 C 3.62682249798082 8.77416472854433 3.68440588596954 9.04048789799212 3.56204118649352 9.2492276794512 C 2.90703014812193 10.3073224337438 2.36718588572777 11.4445943465208 1.9497063228096 12.6250538002894 C -0.130493568282595 18.4985593751379 1.1147471969733 24.7535548954117 4.69211517577197 29.3314342405142 C 6.67874206138249 31.8794991590147 9.39235922035051 33.9093135856167 12.6602164887099 35.060981345391 C 13.236050368597 35.2625232033514 13.8118842484841 35.4352733673176 14.3949160518698 35.5792318372894 C 18.3105864351022 36.5365556626017 22.4062049057992 36.1190760996835 26.0987396605753 34.3555848425293 C 30.3383166012442 32.3329683394258 33.5341946346176 28.7843920546214 35.0961440338114 24.3576691029893 C 38.3280116846779 15.2163062597814 33.5269967111191 5.15360920875412 24.3856338679112 1.9217415578877 C 23.8241958350213 1.72019969992721 23.2483619551341 1.55464745945966 22.672528075247 1.41068898948788 C 20.1748486212367 0.798865492107825 17.5692003147475 0.748480027617699 15.0427291667428 1.25953259601752 C 14.9779478552555 1.27392844301469 14.9131665437682 1.27392844301469 14.8555831557795 1.25233467251892 C 14.6972288388105 1.21634505502598 14.5676662158359 1.08678243205138 14.531676598343 0.914032268085244 C 14.4812911338529 0.676500792631811 14.6396454508218 0.446167240676965 14.8771769262753 0.395781776186839 C 17.526012773756 -0.144062486207328 20.2612237032198 -0.0864790982186222 22.8884657802047 0.554136093155797 C 23.4930913540862 0.698094563127572 24.090519004469 0.8780426505923 24.6879466548519 1.08678243205138 C 34.2827786784709 4.47700439988675 39.3213251274832 15.0507540193138 35.9311031596477 24.6383881194342 C 34.2899766019695 29.2882466995226 30.9285463281285 33.0095731482931 26.4802296060006 35.1329605803768 C 22.6077467637597 36.9828269195142 18.3105864351022 37.4219002529281 14.1933741939093 36.4213888866243 C 13.5815506965292 36.2702324931539 12.9769251226478 36.0902844056892 12.3722995487663 35.8815446242301 C 7.7224409686779 34.2404180665518 3.99391659640884 30.8789877927108 1.8705291643251 26.4306710705829 Z " fill-rule="nonzero" fill="#ffffff" stroke="none" transform="matrix(1 0 0 1 200 131 )" />
</g>
</svg>

6
src/static/images/banner/u2450.svg

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="26px" height="30px" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1 0 0 1 -47 -440 )">
<path d="M 0 5.43375 C 0 4.39821609406726 0.831471178885669 3.55875 1.85714285714286 3.55875 L 4.667 3.55875 L 4.667 9 L 20.6142857142857 9 L 20.6142857142857 3.55875 L 24.1428571428571 3.55875 C 25.1685288211143 3.55875 26 4.39821609406726 26 5.43375 L 26 28.125 C 26 29.1605339059327 25.1685288211143 30 24.1428571428571 30 L 1.85714285714286 30 C 0.831471178885669 30 0 29.1605339059327 0 28.125 L 0 5.43375 Z M 6.68571428571429 7.213125 L 6.68571428571429 2.638125 L 8.54657142857143 2.638125 C 8.54657142857143 1.18125 9.71657142857143 0 11.1614285714286 0 L 14.1328571428571 0 C 15.5758571428571 0 16.7458571428571 1.18125 16.7458571428571 2.638125 L 18.5714285714286 2.638125 L 18.5714285714286 7.213125 L 6.68571428571429 7.213125 Z M 10.8958571428571 3.178125 C 10.8958571428571 4.231875 11.726 5.085 12.753 5.085 C 13.7781428571429 5.085 14.6101428571429 4.231875 14.6101428571429 3.178125 C 14.6101428571429 2.124375 13.7781428571429 1.27125 12.753 1.27125 C 11.726 1.27125 10.8958571428571 2.124375 10.8958571428571 3.178125 Z M 21.7898571428571 12 L 4.21014285714286 12 L 4.21014285714286 14 L 21.7898571428571 14 L 21.7898571428571 12 Z M 4.21014285714286 15.76125 L 4.21014285714286 15.763125 L 4.21014285714286 17.5425 L 8.17142857142857 17.5425 L 8.17142857142857 15.76125 L 4.21014285714286 15.76125 Z M 4.21014285714286 19.83 L 4.21014285714286 19.831875 L 4.21014285714286 21.609375 L 8.17142857142857 21.609375 L 8.17142857142857 19.83 L 4.21014285714286 19.83 Z M 4.21014285714286 23.896875 L 4.21014285714286 23.89875 L 4.21014285714286 25.678125 L 9.16128571428571 25.678125 L 9.16128571428571 23.896875 L 4.21014285714286 23.896875 Z M 19.1007142857143 22.936875 C 18.6304250353497 23.601697854168 18.054348350795 24.1833137376127 17.3958571428571 24.658125 C 17.3499258944188 24.6907879240536 17.3226001725233 24.743965009545 17.3226001725233 24.800686363582 C 17.3226001725233 24.8471234159694 17.3409461471698 24.8916424010547 17.3735714285714 24.924375 L 19.955 27.530625 C 20.0943364195914 27.6714577822726 20.2834102728407 27.7505899923118 20.4805714285714 27.7505899923118 C 20.6777325843022 27.7505899923118 20.8668064375515 27.6714577822726 21.0061428571429 27.530625 L 21.9495714285714 26.578125 C 22.0890629462509 26.4374488071433 22.1674415161946 26.2465569360743 22.1674415161946 26.0475 C 22.1674415161946 25.8484430639257 22.0890629462509 25.6575511928567 21.9495714285714 25.516875 L 19.3718571428571 22.914375 C 19.3384169107129 22.8805790204336 19.2930418828892 22.8615897586197 19.2457262895471 22.8615897586197 C 19.1881881961978 22.8615897586197 19.1341869943616 22.8896253240047 19.1007142857143 22.936875 Z M 14.759255467994 24.5140374791424 C 15.8204396264006 24.5140374791424 16.8379731597654 24.0875460419895 17.5871428571429 23.32875 C 18.3393810181837 22.5713714085468 18.7621586915612 21.5428888032805 18.7621586915612 20.4703129946648 C 18.7621586915612 19.4014123902587 18.3422653206105 18.3761442986165 17.5945714285714 17.619375 C 16.4639051022835 16.4793931723658 14.7689506313882 16.1297666636769 13.286 16.730625 C 13.2322852506052 16.7522006308877 13.1970325664254 16.804665558827 13.1970325664254 16.8630310876505 C 13.1970325664254 16.9004978712548 13.2116477538362 16.9364572975827 13.2377142857143 16.963125 L 14.4857142857143 18.223125 C 14.702965366557 18.4427381600805 14.702965366557 18.7985118399195 14.4857142857143 19.018125 L 13.2637142857143 20.251875 C 13.1592443813362 20.3572532390508 13.017609951532 20.4164460384021 12.8699345449049 20.4164460384021 C 12.7186473849234 20.4164460384021 12.5738649451232 20.3543311831856 12.4688571428571 20.244375 L 11.2524285714286 18.97125 C 11.228278977567 18.9459814310735 11.1949935626667 18.9317087237978 11.160214266276 18.9317087237978 C 11.1072954788903 18.9317087237978 11.0598197467671 18.9645509214797 11.0407142857143 19.014375 C 10.8594350431001 19.4823089185733 10.7663983251369 19.9803341788901 10.7663983251369 20.4827874791424 C 10.7663983251369 22.7091853768978 12.5540613597411 24.5140374791424 14.759255467994 24.5140374791424 Z M 21.0771333988002 25.9865625 C 21.0771333988002 26.1605123044669 21.0088694902987 26.3273761781034 20.8872857142857 26.450625 C 20.7650596956061 26.5745248598445 20.5989889589728 26.6441731430195 20.4257857142857 26.6441731430195 C 20.0660563212907 26.6441731430195 19.7744380297712 26.3497508294661 19.7744380297712 25.9865625 C 19.7744380297712 25.8126126955331 19.8427019382728 25.6457488218966 19.9642857142857 25.5225 C 20.0865117329653 25.3986001401555 20.2525824695986 25.3289518569805 20.4257857142857 25.3289518569805 C 20.7855151072807 25.3289518569805 21.0771333988002 25.6233741705339 21.0771333988002 25.9865625 Z " fill-rule="nonzero" fill="#9bca63" stroke="none" transform="matrix(1 0 0 1 47 440 )" />
</g>
</svg>

6
src/static/images/banner/u253_selected.svg

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="20px" height="18px" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1 0 0 1 -30 -16 )">
<path d="M 19.7374790983607 8.04830870454546 C 19.9665962704918 7.76331261818182 19.9137230737705 7.351651575 19.6317327254098 7.12646946818182 L 11.2566194672131 0.571559031818182 C 10.5410689754098 0.00508528636363643 9.42015733606558 0.00508528636363643 8.70460684426229 0.571559031818182 L 0.392941434426229 7.12998793636364 C 0.107426209016393 7.35517004318182 0.0616027868852459 7.76683108636364 0.28367018442623 8.048308725 C 0.505737581967213 8.32978636363636 0.921673340163934 8.37904493863636 1.20366368852459 8.1573813 L 1.47155450819672 7.94627306590909 L 1.47155450819672 15.8733869727273 C 1.47155450819672 16.9957790386364 2.63828956967213 17.8366934863636 3.68165383196721 17.8366934863636 L 16.7942048770492 17.8366934863636 C 17.8234696311475 17.8366934863636 18.5178708606557 17.0485561022727 18.5178708606557 15.8733869727273 L 18.5178708606557 7.92516225681818 L 18.8139607172131 8.1573813 C 18.9338066188525 8.25238000227273 19.0748017827869 8.29812010909091 19.2193218442623 8.29812010909091 C 19.413190204918 8.29812010909091 19.6070585655738 8.21367681136364 19.7374790983607 8.04830870454546 Z M 11.9651202254098 15.1591374818182 L 11.9651202254098 16.5243040159091 L 10.6538651229508 16.5243040159091 L 9.3426100204918 16.5243040159091 L 8.03135491803279 16.5243040159091 L 8.03135491803279 15.1591374818182 L 8.03135491803279 12.8615762863636 C 8.03135491803279 12.1015866681818 8.64820879098361 11.28178305 9.99823758196722 11.28178305 C 11.3517912295082 11.28178305 11.9651202459016 12.1015866681818 11.9651202459016 12.8615762863636 L 11.9651202254098 15.1591374818182 Z " fill-rule="nonzero" fill="#0052d9" stroke="none" transform="matrix(1 0 0 1 30 16 )" />
</g>
</svg>

BIN
src/static/images/bg.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

BIN
src/static/images/default.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
src/static/images/icon1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

1
src/static/images/icon1.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="86" height="86" viewBox="0 0 86 86"><g><g><ellipse cx="43" cy="43" rx="43" ry="43" fill="#DAF9F4" fill-opacity="1"/></g><g><g><g><path d="M24.384619999999998,20L61.6154,20C63.5333,20,65,21.48571,65,23.42857L65,64.5714C65,66.51429999999999,63.5333,68,61.6154,68L24.384619999999998,68C22.46667,68,21,66.51429999999999,21,64.5714L21,23.42857C21,21.48571,22.46667,20,24.384619999999998,20Z" fill="#09D3B6" fill-opacity="1"/></g><g><path d="M37.85714,16.469839999999998C38.08571,14.01143,40.371430000000004,12,43,12C45.6286,12,47.8,14.01143,48.1429,16.469839999999998L52.7143,16.469839999999998C53.9714,16.469839999999998,55,17.47556,55,18.70476L55,22.0571C55,23.2863,53.9714,24.292099999999998,52.7143,24.292099999999998L33.28571,24.292099999999998C32.02857,24.292099999999998,31,23.2863,31,22.0571L31,18.70476C31,17.47556,32.02857,16.469839999999998,33.28571,16.469839999999998L37.85714,16.469839999999998Z" fill="#A5ECE2" fill-opacity="1"/></g><g><rect x="28" y="30" width="30" height="3" rx="1.5" fill="#A5ECE2" fill-opacity="1"/></g><g><rect x="28" y="39" width="30" height="3" rx="1.5" fill="#A5ECE2" fill-opacity="1"/></g><g><rect x="28" y="48" width="12" height="3" rx="1.5" fill="#A5ECE2" fill-opacity="1"/></g><g><rect x="28" y="57" width="12" height="3" rx="1.5" fill="#A5ECE2" fill-opacity="1"/></g></g><g><path d="M55.0518,55.0411C54.9959,55.1612,54.9345,55.28009,54.8672,55.39658L53.3279,58.085499999999996C55.0584,57.417699999999996,56.4,57.7078,57.3516,58.9561C57.4707,59.1125,57.4106,59.340199999999996,57.2301,59.4161L49.82228,62.5283C47.93876,63.438199999999995,45.6871,63.004999999999995,44.26822,61.4596C42.84935,59.9142,42.594156,57.6171,43.638749,55.79348L46.61558,50.593469999999996L48.69979,46.952854C49.03085,46.383296,49.75577,46.190005,50.32276,46.520105C50.88976,46.850204,51.08619,47.5799,50.76255,48.15378L51.65578,46.593775C51.986869999999996,46.0242674,52.71176,45.831011,53.2787,46.161094C53.8457,46.491177,54.0421,47.22083,53.7185,47.7947L54.314,46.754699C54.6451,46.185189,55.37,45.99193163,55.937,46.322016C56.5039,46.652101,56.7004,47.38175,56.3768,47.95563L55.7813,48.99563C56.1124,48.42603,56.8373,48.2327,57.4043,48.56281C57.9713,48.89293,58.1678,49.62267,57.8441,50.19656L55.1644,54.876580000000004C55.131,54.93542,55.0929,54.99066,55.0512,55.0411L55.0518,55.0411Z" fill="#A5ECE2" fill-opacity="1"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
src/static/images/icon2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

1
src/static/images/icon2.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="86" height="86" viewBox="0 0 86 86"><g><g><ellipse cx="43" cy="43" rx="43" ry="43" fill="#E6FBFF" fill-opacity="1"/></g><g><g><path d="M30.30769,23L55.6923,23C57,23,58,24.00816,58,25.326529999999998L58,53.2449C58,54.5633,57,55.5714,55.6923,55.5714L30.30769,55.5714C29,55.5714,28,54.5633,28,53.2449L28,25.326529999999998C28,24.00816,29,23,30.30769,23Z" fill="#B6F3FF" fill-opacity="1"/></g><g><path d="M39.49350199157715,22.03311C39.64935199157715,20.3649,41.207791991577146,19,43.00000199157715,19C44.79221199157715,19,46.272681991577144,20.3649,46.50648199157715,22.03311L49.62338199157715,22.03311C50.48048199157715,22.03311,51.181781991577154,22.71556,51.181781991577154,23.54966L51.181781991577154,25.82449C51.181781991577154,26.65859,50.48048199157715,27.34104,49.62338199157715,27.34104L36.376621991577146,27.34104C35.51948099157715,27.34104,34.81818199157715,26.65859,34.81818199157715,25.82449L34.81818199157715,23.54966C34.81818199157715,22.71556,35.51948099157715,22.03311,36.376621991577146,22.03311L39.49350199157715,22.03311Z" fill="#3DE0FF" fill-opacity="1"/></g><g><rect x="33" y="31" width="20" height="2" rx="1" fill="#3DE0FF" fill-opacity="1"/></g><g><rect x="33" y="37" width="20" height="2" rx="1" fill="#3DE0FF" fill-opacity="1"/></g><g><rect x="33" y="43" width="20" height="2" rx="1" fill="#3DE0FF" fill-opacity="1"/></g></g><g transform="matrix(-1,0,0,1,138,0)"><path d="M120.61500000000001,56.00189L109.4822,47.199679C109.3201,47.0712688,109.1128,47.000385522,108.8982,47L90.7964,47C90.1353,46.999822784,89.508,47.266946,89.0835,47.729443C87.8195,49.10784,88.4873,50.45466,91.0857,51.7699L99.1422,53.25935L94.9324,55.42017L84.7007,55.42017L75.10776,49.14758C73.7611,48.50881,72.7874,48.2103,72.18553,48.25309C69.0667771,48.47723,68.050643,50.52292,69.979067,52.71125L82.1682,62.4385L104.0754,62.4385L109.9545,66.7734C110.4137,67.1122,111.0826,67.0662,111.48089999999999,66.6685L120.7077,57.4587C121.13130000000001,57.0357,121.0894,56.37732,120.61500000000001,56.00189Z" fill="#3DE0FF" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
src/static/images/icon3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

1
src/static/images/icon3.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="86" height="86" viewBox="0 0 86 86"><g><g><ellipse cx="43" cy="43" rx="43" ry="43" fill="#FFE5E3" fill-opacity="1"/></g><g><g><g><path d="M24.384619999999998,20L61.6154,20C63.5333,20,65,21.48571,65,23.42857L65,64.5714C65,66.51429999999999,63.5333,68,61.6154,68L24.384619999999998,68C22.46667,68,21,66.51429999999999,21,64.5714L21,23.42857C21,21.48571,22.46667,20,24.384619999999998,20Z" fill="#FC4F42" fill-opacity="1"/></g><g><path d="M37.85714,16.469839999999998C38.08571,14.01143,40.371430000000004,12,43,12C45.6286,12,47.8,14.01143,48.1429,16.469839999999998L52.7143,16.469839999999998C53.9714,16.469839999999998,55,17.47556,55,18.70476L55,22.0571C55,23.2863,53.9714,24.292099999999998,52.7143,24.292099999999998L33.28571,24.292099999999998C32.02857,24.292099999999998,31,23.2863,31,22.0571L31,18.70476C31,17.47556,32.02857,16.469839999999998,33.28571,16.469839999999998L37.85714,16.469839999999998Z" fill="#FABEB9" fill-opacity="1"/></g><g><rect x="28" y="30" width="30" height="3" rx="1.5" fill="#FABEB9" fill-opacity="1"/></g><g><rect x="28" y="39" width="30" height="3" rx="1.5" fill="#FABEB9" fill-opacity="1"/></g><g><rect x="28" y="48" width="12" height="3" rx="1.5" fill="#FABEB9" fill-opacity="1"/></g><g><rect x="28" y="57" width="12" height="3" rx="1.5" fill="#FABEB9" fill-opacity="1"/></g></g><g><g transform="matrix(0.7019045352935791,-0.7122711539268494,0.7122711539268494,0.7019045352935791,-22.868730311578474,50.437727685777645)"><path d="M48.82373046875 52.540191650390625C48.82373046875 52.540191650390625 48.82373046875 52.540191650390625 48.82373046875 52.540191650390625L51.98373055458069 52.540191650390625C51.98373055458069 52.540191650390625 51.98373055458069 52.540191650390625 51.98373055458069 52.540191650390625L51.98373055458069 65.49274146556854C51.98373055458069 66.36535139400269 51.27634044009949 67.07274150848389 50.403730511665344 67.07274150848389L50.403730511665344 67.07274150848389C49.5311205832312 67.07274150848389 48.82373046875 66.36535139400269 48.82373046875 65.49274146556854Z" fill="#FABEB9" fill-opacity="1"/></g><g><path d="M44.449065,48.02400002861023L46.53273,50.54400002861023L48.83194,48.24000002861023L46.38903,46.15200002861023C46.96383,45.86400002861023,47.61048,45.72000002861023,48.32899,45.72000002861023C50.70005,45.72000002861023,52.640010000000004,47.66400002861023,52.640010000000004,50.04000002861023C52.640010000000004,52.41600002861023,50.70005,54.36000002861023,48.32899,54.36000002861023C45.95792,54.36000002861023,44.0179626,52.41600002861023,44.0179626,50.04000002861023C43.9461122,49.32000002861023,44.089813,48.67200002861023,44.449065,48.02400002861023Z" fill="#FABEB9" fill-opacity="1"/></g><g><path d="M58.913470312499996,52.23621L52.1999803125,61.8521C51.3729503125,63.066199999999995,49.7188903125,63.357600000000005,48.5026703125,62.532L48.4053763125,62.4349C47.3351047125,61.609300000000005,47.0918613125,60.0066,47.9675383125,58.9382C48.0161873125,58.8896,48.0648353125,58.792500000000004,48.1621333125,58.7439L56.2864703125,50.24503L57.1135003125,46.69978L60.4702703125,45L62.9999703125,46.94261L62.1242703125,50.58499L58.913470312499996,52.23621Z" fill="#FABEB9" fill-opacity="1"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

1
src/static/images/icon4.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.1 KiB

1
src/static/images/icon5.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="86" height="86" viewBox="0 0 86 86"><g><g><ellipse cx="43" cy="43" rx="43" ry="43" fill="#FFF3E2" fill-opacity="1"/></g><g><g><path d="M24.384619999999998,20L61.6154,20C63.5333,20,65,21.48571,65,23.42857L65,64.5714C65,66.51429999999999,63.5333,68,61.6154,68L24.384619999999998,68C22.46667,68,21,66.51429999999999,21,64.5714L21,23.42857C21,21.48571,22.46667,20,24.384619999999998,20Z" fill="#FBB03B" fill-opacity="1"/></g><g><path d="M37.85714,16.469839999999998C38.08571,14.01143,40.371430000000004,12,43,12C45.6286,12,47.8,14.01143,48.1429,16.469839999999998L52.7143,16.469839999999998C53.9714,16.469839999999998,55,17.47556,55,18.70476L55,22.0571C55,23.2863,53.9714,24.292099999999998,52.7143,24.292099999999998L33.28571,24.292099999999998C32.02857,24.292099999999998,31,23.2863,31,22.0571L31,18.70476C31,17.47556,32.02857,16.469839999999998,33.28571,16.469839999999998L37.85714,16.469839999999998Z" fill="#FFCE82" fill-opacity="1"/></g><g><rect x="28" y="30" width="30" height="3" rx="1.5" fill="#FFCE82" fill-opacity="1"/></g><g><rect x="28" y="39" width="30" height="3" rx="1.5" fill="#FFCE82" fill-opacity="1"/></g><g><rect x="28" y="48" width="12" height="3" rx="1.5" fill="#FFCE82" fill-opacity="1"/></g><g><rect x="28" y="57" width="12" height="3" rx="1.5" fill="#FFCE82" fill-opacity="1"/></g><g><g transform="matrix(0.7381733059883118,-0.6746111512184143,0.6746111512184143,0.7381733059883118,-23.766510171255504,48.81186932972196)"><path d="M51 55.0238037109375C51 55.0238037109375 51 55.0238037109375 51 55.0238037109375L54.00000023841858 55.0238037109375C54.00000023841858 55.0238037109375 54.00000023841858 55.0238037109375 54.00000023841858 55.0238037109375L54.00000023841858 63.66980063915253C54.00000023841858 64.4982278297362 53.32842730979295 65.16980075836182 52.50000011920929 65.16980075836182L52.50000011920929 65.16980075836182C51.67157292862563 65.16980075836182 51 64.4982278297362 51 63.66980063915253Z" fill="#FFCE82" fill-opacity="1"/></g><g><path d="M44.623701,49.2L47.51767,52.7L50.71102,49.5L47.31809,46.6C48.11642,46.2,49.01455,46,50.01247,46C53.30561,46,56,48.7,56,52C56,55.3,53.30561,58,50.01247,58C46.71933,58,44.024948,55.3,44.024948,52C43.9251559,51,44.12474,50.1,44.623701,49.2Z" fill="#FFCE82" fill-opacity="1"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/static/images/icon6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/static/images/icon7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/static/images/icon8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/static/images/mobile_bg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

BIN
src/static/images/photo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
src/static/images/profile.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
src/static/images/tabbar/tab_act_icon1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/static/images/tabbar/tab_act_icon2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/static/images/tabbar/tab_act_icon3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
src/static/images/tabbar/tab_act_icon4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
src/static/images/tabbar/tab_act_icon5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/static/images/tabbar/tab_icon1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/static/images/tabbar/tab_icon2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/static/images/tabbar/tab_icon3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
src/static/images/tabbar/tab_icon4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
src/static/images/tabbar/tab_icon5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

1
src/store/index.ts

@ -0,0 +1 @@
export { default as useCountStore } from './modules/countStore'

124
src/store/modules/countStore.ts

@ -0,0 +1,124 @@
import { defineStore } from 'pinia'
import {
login,
logout,
getInfo,
getPermissionInfo
} from '@/api/login'
import {
setToken,
removeToken
} from '@/utils/auth'
const baseUrl = import.meta.env.VITE_BASE_URL
const useStore = defineStore('storeId', {
state: () => ({
id: '', // 用户编号
name: '',
avatar: '',
roles: [],
permissions: '',
role: '',
post: '',
dept: '',
meaus: [],
}),
getters: {
// isEven: (state) => state.count % 2 === 0
},
actions: {
// 登录
Login(userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password
const captchaVerification = userInfo.captchaVerification
const tenantName = userInfo.tenantName
const rememberMe = userInfo.rememberMe
const code = userInfo.code
const uuid = userInfo.uuid
return new Promise((resolve, reject) => {
login(username, password, captchaVerification, tenantName, rememberMe, code, uuid).then(
res => {
res = res.data;
// 设置 token
setToken(res)
resolve(res)
}).catch(error => {
reject(error)
})
})
},
// 获取权限
GetPermissionInfo() {
return new Promise((resolve, reject) => {
getPermissionInfo().then(res => {
res = res.data; // 读取 data 数据
if (res.roles && res.roles.length > 0) {
this.roles = res.roles
this.role = res.roles.filter(item => item == 'all_approve' || item == 'normal_approve')[0]
this.permissions = res.permissions
uni.setStorageSync('permissionInfo',res.permissions)
uni.setStorageSync('roles',res.roles)
let menus = []
res.menus.forEach(item => {
if (item.path == '/pda') {
menus = item.children
}
})
this.meaus = menus
} else {
this.roles = []
this.role = ''
}
resolve(res)
}).catch(error => {
reject(error)
})
})
},
// 获取权限
GetInfo() {
return new Promise((resolve, reject) => {
getInfo().then(res => {
res = res.data; // 读取 data 数据
this.avatar = res.avatar
this.name = res.nickname
this.id = res.id
this.avatar = res.avatar
this.dept = res.dept
if (res.posts && res.posts.length > 0) {
this.post = res.posts.filter(item => item.code == 'worker' || item.code == 'engineer')[0]
} else {
this.post = ''
}
resolve(res)
}).catch(error => {
reject(error)
})
})
},
// 获取权限
LogOut() {
return new Promise((resolve, reject) => {
logout().then(res => {
this.id = ''// 用户编号
this.name = ''
this.avatar = ''
this.roles = ''
this.permissions = ''
this.role = ''
this.post = ''
this.dept = ''
removeToken()
uni.removeStorageSync('permissionInfo')
uni.removeStorageSync('roles')
resolve(res)
}).catch(error => {
reject(error)
})
})
},
}
})
export default useStore

2
src/styles/vars/_base.less

@ -0,0 +1,2 @@
@title-size: 40rpx;
@title-color: #47caff;

2
src/styles/vars/_base.scss

@ -0,0 +1,2 @@
$title-size: 40rpx;
$title-color: #bd34fe;

77
src/uni.scss

@ -0,0 +1,77 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量同时无需 import 这个文件
*/
@import 'vk-uview-ui/theme.scss';
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color: #333; //基本色
$uni-text-color-inverse: #fff; //反色
$uni-text-color-grey: #999; //辅助灰色如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable: #c0c0c0;
/* 背景颜色 */
$uni-bg-color: #ffffff;
$uni-bg-color-grey: #f8f8f8;
$uni-bg-color-hover: #f1f1f1; //点击状态颜色
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); //遮罩颜色
/* 边框颜色 */
$uni-border-color: #c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm: 24rpx;
$uni-font-size-base: 28rpx;
$uni-font-size-lg: 32rpx;
/* 图片尺寸 */
$uni-img-size-sm: 40rpx;
$uni-img-size-base: 52rpx;
$uni-img-size-lg: 80rpx;
/* Border Radius */
$uni-border-radius-sm: 4rpx;
$uni-border-radius-base: 6rpx;
$uni-border-radius-lg: 12rpx;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 10px;
$uni-spacing-row-base: 20rpx;
$uni-spacing-row-lg: 30rpx;
/* 垂直间距 */
$uni-spacing-col-sm: 8rpx;
$uni-spacing-col-base: 16rpx;
$uni-spacing-col-lg: 24rpx;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2c405a; // 文章标题颜色
$uni-font-size-title: 40rpx;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle: 36rpx;
$uni-color-paragraph: #3f536e; // 文章段落颜色
$uni-font-size-paragraph: 30rpx;

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save