Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
deer
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
viitto
deer
Commits
64ac1237
Commit
64ac1237
authored
Sep 29, 2021
by
罗超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增,登录模拟和注册模拟,修复之前不合理的调用,新增一些组件
parent
883c93f6
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
753 additions
and
184 deletions
+753
-184
README.md
README.md
+19
-90
quasar.conf.js
quasar.conf.js
+1
-1
enumHelper.ts
src/@types/enumHelper.ts
+33
-0
index.ts
src/@types/index.ts
+2
-19
14.png
src/assets/images/14.png
+0
-0
permission.ts
src/boot/permission.ts
+8
-5
verifyCode.vue
src/components/common/verifyCode.vue
+95
-0
app.ts
src/config/app.ts
+3
-2
dictionary.ts
src/config/dictionary.ts
+2
-1
font.sass
src/css/font.sass
+7
-1
metaModule.ts
src/module/meta/metaModule.ts
+24
-0
scrollModule.ts
src/module/scrollbar/scrollModule.ts
+28
-0
loginModule.ts
src/module/user/loginModule.ts
+58
-13
registModule.ts
src/module/user/registModule.ts
+208
-0
Index.vue
src/pages/Index.vue
+8
-13
login.vue
src/pages/auth/login.vue
+22
-12
regist.vue
src/pages/auth/regist.vue
+126
-0
routes.ts
src/router/routes.ts
+7
-3
actions.ts
src/store/modules/user/actions.ts
+45
-17
getters.ts
src/store/modules/user/getters.ts
+4
-2
state.ts
src/store/modules/user/state.ts
+2
-2
auth.ts
src/utils/auth.ts
+2
-1
message.ts
src/utils/message.ts
+21
-2
tools.ts
src/utils/tools.ts
+28
-0
No files found.
README.md
View file @
64ac1237
<a
name=
"lgzKP"
></a>
# Ocss App (ocss)
## 项目框架:
项目采用Quasar+Vue3.2+TS,构建。开发中需要严格遵守TS协议,语法,对象等标准。严厉杜绝直接使用JS的弱类型。严格遵守composition api,杜绝Option api。项目后期会加入Vite2作为打包工具,放弃Webpack。
> 项目弃用了ESLint语法约束,开发人员需要按照Prettier 格式化代码,并且处理语法不合规的内容,严禁关闭ESLint语法验证。
<br
/>
niuu bee
<a
name=
"WJ7J1"
></a>
## 第三方依赖:
> cnpm i -S @types/webpack-env 自动注入
> cnpm i -S vuex-persistedstate 持久化Store
> cnpm install --save @types/lockr LocalStorage管理工具
> cnpm install --save @types/lodash JS 原生库,封装了许多实用方法,项目使用初衷为全局组件注册的一致性
注意Store已加入自动化注入功能,请按照示例格式进行添加
<br
/>
store的持久化需要在index.ts文件中进行配置
## Install the dependencies
```
typescript
```
bash
process
.
env
.
NODE_ENV
!==
'production'
yarn
?
[
createLogger
(),
createPersistedState
({
paths
:
[
'app'
,
'user'
,
'你的Store名称'
]
})
]
:
[
createPersistedState
({
paths
:
[
'app'
,
'user'
,
'你的Store名称'
]
})
]
```
```
<a
name=
"GdhGb"
></a>
## 项目基础架构说明:
### Start the app in development mode (hot-code reloading, error reporting, etc.)
```
bash
quasar dev
```
### Lint the files
```
bash
yarn run lint
```
```
|-- 根目录
|-- quasar-cli文件,不需要做调整
|-- dist 项目 build 之后的文件夹
|-- public 项目静态资源,不经过 webpack,以及默认的模版,适合存放第三方压缩好的资源
|-- src 主要的开发目录
| |-- @types 项目共用的 type
| |-- App.vue 页面渲染根节点
| |-- main.ts 入口文件
| |-- shims-vue.d.ts vue 文件类型的 type
| |-- api 封装http请求相关(持久层)
| | |-- apiList.ts api接口列表(弃用,在各自的Service中维护)
| | |-- axios.ts 业务请求封装 (封装Request AOP)
| | |-- Common.ts 公共模块的的网络请求,所有通用 api 放在此处(例如请求枚举之类)
| | |-- user.ts 用户请求模块(示例)
| |-- assets 存放静态资源,这个文件夹下的文件会走 webpack 压缩流程
| |-- boot quasar全局组件封装目录
| | |-- axios.ts 弃用
| | |-- dict.ts 字典库(用于魔法值的封装,注意项目全局不能存在魔法值)
| | |-- i18n.ts 国际化
| | |-- permission.ts 路由权限封装
| |-- components
| | |-- index.ts 自动注册脚本
| | |-- global 自动注册的全局组件
| | |-- ...其他非全局注册的模块(按照实际需要创建目录管理组件,严禁直接在cmp根目录创建)
| |-- config 全局静态配置,不可更改项
| | |-- app.ts 全局配置信息
| | |-- color.ts 示例
| | |-- dictionary.ts 魔法值定义类,按照项目需要自行创建部分类
| |-- css 样式存放目录(注意遵从Sass或Scss创建,不允许使用原生CSS)
| |-- i18n 国际化配置
| |-- layout 页面页面骨架
| |-- module 遵从Vue3.x cmpApi对Setup进行拆分封装,按照领域划分文件夹,类名+Module
| | |-- user
| | | |-- loginModule.ts 示例:内部应该遵从usexxxxModule规范命名
| |-- pages 页面级组件
| |-- router 路由
| | |-- index.ts 路由入口
| |-- store vuex
| | |-- modules 多个模块
| | |-- index.ts 自动装载模块
| | |-- app app 模块
| |-- utils 常用函数以及其他有用工具
| | |-- auth.ts 身份验证中间件
| | |-- message.ts 消息组件封装
| | |-- tools.ts 工具类
| | |-- validate.ts 验证封装
|-- .czrc 提交规范选项设置
|-- .editorconfig vscode 编辑器 设置
|-- .env.development 开发环境配置
|-- .env.preview 测试环境配置
|-- .env.production 生产环境配置
|-- .eslintignore eslint 要忽略的文件夹
|-- .eslintrc.js eslint 规则配置
|-- .gitignore git 忽略的文件
|-- .prettierrc.js 格式化插件配置
|-- README.md 项目说明
|-- babel.config.js babel 设置
|-- package.json npm 配置
|-- tsconfig.json typescript 配置
|-- typedoc.json 文档配置文件
|-- quasar.conf.js quasar 脚手架配置文件
### Build the app for production
```
bash
quasar build
```
```
<br
/>
### Customize the configuration
<br
/>
<br
/>
See
[
Configuring quasar.conf.js
](
https://v2.quasar.dev/quasar-cli/quasar-conf-js
)
.
quasar.conf.js
View file @
64ac1237
...
@@ -112,7 +112,7 @@ module.exports = configure(function (ctx) {
...
@@ -112,7 +112,7 @@ module.exports = configure(function (ctx) {
directives
:
[
'ClosePopup'
],
directives
:
[
'ClosePopup'
],
// Quasar plugins
// Quasar plugins
plugins
:
[]
plugins
:
[
'Notify'
,
'SessionStorage'
,
'Dialog'
]
},
},
animations
:
'all'
,
// --- includes all animations
animations
:
'all'
,
// --- includes all animations
...
...
src/@types/enumHelper.ts
0 → 100644
View file @
64ac1237
export
enum
RoleType
{
'超级管理员'
=
1
,
'子账号'
,
'团队超级管理员'
,
'团队管理员'
,
'团队成员'
,
'团队访客'
,
'项目管理员'
,
'项目成员'
,
'项目访客'
}
/**
* @description 常用异常结果常量定义
*/
export
enum
ResultType
{
'Empty'
=
1
,
'Null'
=
2
,
'EmptyArray'
=
3
}
export
enum
IndustryType
{
'请选择'
=
0
,
'旅游行业'
=
1
,
'教育行业'
=
2
}
export
enum
ScaleType
{
'请选择'
=
0
,
'1-20人'
=
1
,
'21-50人'
=
2
,
'51-100人'
=
3
,
'100人以上'
=
4
}
src/@types/index.ts
View file @
64ac1237
import
{
AppStateType
}
from
'@/store/modules/app/state'
import
{
AppStateType
}
from
'@/store/modules/app/state'
import
{
UserStateType
}
from
'@/store/modules/user/state'
import
{
UserStateType
}
from
'@/store/modules/user/state'
import
{
TeamStateType
}
from
'@/store/modules/user/modules/team/state'
import
{
TeamStateType
}
from
'@/store/modules/user/modules/team/state'
import
{
RoleType
}
from
'./enumHelper'
// vuex state 的模块的类型
// vuex state 的模块的类型
type
ModuleType
=
{
type
ModuleType
=
{
...
@@ -27,14 +28,7 @@ export type IconType = 'icon' | 'iconfont'
...
@@ -27,14 +28,7 @@ export type IconType = 'icon' | 'iconfont'
// 对话框打开类型
// 对话框打开类型
export
type
ModalOpenMode
=
'edit'
|
'add'
|
'other'
export
type
ModalOpenMode
=
'edit'
|
'add'
|
'other'
/**
* @description 常用异常结果常量定义
*/
export
enum
ResultType
{
'Empty'
=
1
,
'Null'
=
2
,
'EmptyArray'
=
3
}
//TODO: 请根据实际情况调整定义的实体对象
//TODO: 请根据实际情况调整定义的实体对象
/**
/**
* @description 模拟定义菜单信息
* @description 模拟定义菜单信息
...
@@ -121,17 +115,6 @@ export interface TeamMemberType {
...
@@ -121,17 +115,6 @@ export interface TeamMemberType {
cloudRole
?:
string
cloudRole
?:
string
}
}
export
enum
RoleType
{
'超级管理员'
=
1
,
'子账号'
,
'团队超级管理员'
,
'团队管理员'
,
'团队成员'
,
'团队访客'
,
'项目管理员'
,
'项目成员'
,
'项目访客'
}
// 权限列表类型
// 权限列表类型
export
interface
RoleItemType
{
export
interface
RoleItemType
{
...
...
src/assets/images/14.png
0 → 100644
View file @
64ac1237
30.1 KB
src/boot/permission.ts
View file @
64ac1237
import
{
ResultType
,
AuthMenuType
}
from
'@/@types'
import
{
AuthMenuType
}
from
'@/@types'
import
{
ResultType
}
from
'@/@types/enumHelper'
import
router
from
'@/router/index'
import
router
from
'@/router/index'
import
{
getAuth
,
getUserAllMenu
}
from
'@/utils/auth'
import
{
getAuth
,
getUserAllMenu
}
from
'@/utils/auth'
...
@@ -11,7 +12,7 @@ LoadingBar.setDefaults({
...
@@ -11,7 +12,7 @@ LoadingBar.setDefaults({
let
loadAsyncRouter
=
false
let
loadAsyncRouter
=
false
const
whiteList
=
[
'/auth/login'
]
const
whiteList
=
[
'/auth/login'
,
'/auth/regist'
]
router
.
beforeEach
((
to
,
from
,
next
)
=>
{
router
.
beforeEach
((
to
,
from
,
next
)
=>
{
localStorage
.
setItem
(
'routerBefore'
,
from
.
path
)
localStorage
.
setItem
(
'routerBefore'
,
from
.
path
)
...
@@ -20,15 +21,14 @@ router.beforeEach((to, from, next) => {
...
@@ -20,15 +21,14 @@ router.beforeEach((to, from, next) => {
if
(
getAuth
())
{
if
(
getAuth
())
{
//debugger;
//debugger;
if
(
to
.
path
===
'/auth/login'
||
to
.
path
===
'/'
)
{
if
(
to
.
path
===
'/auth/login'
||
to
.
path
===
'/'
)
{
next
({
next
(
'/index'
)
path
:
'/home'
})
LoadingBar
.
stop
()
LoadingBar
.
stop
()
}
else
{
}
else
{
if
(
!
loadAsyncRouter
)
{
if
(
!
loadAsyncRouter
)
{
// 判断当前用户是否获取权限
// 判断当前用户是否获取权限
loadAsyncRouter
=
true
loadAsyncRouter
=
true
const
allAuth
=
getUserAllMenu
()
const
allAuth
=
getUserAllMenu
()
console
.
log
(
allAuth
)
if
(
allAuth
!=
ResultType
.
EmptyArray
)
{
if
(
allAuth
!=
ResultType
.
EmptyArray
)
{
//TODO: 动态生成并追加路由 //router.addRoutes(store.getters.addRouters);
//TODO: 动态生成并追加路由 //router.addRoutes(store.getters.addRouters);
// if (to.path === '/404') {
// if (to.path === '/404') {
...
@@ -36,9 +36,12 @@ router.beforeEach((to, from, next) => {
...
@@ -36,9 +36,12 @@ router.beforeEach((to, from, next) => {
// next(to.redirectedFrom || '/')
// next(to.redirectedFrom || '/')
// } else {
// } else {
//检查是否有权限访问
//检查是否有权限访问
const
authMenu
=
allAuth
.
findIndex
((
x
:
AuthMenuType
)
=>
{
const
authMenu
=
allAuth
.
findIndex
((
x
:
AuthMenuType
)
=>
{
console
.
log
(
x
.
menuUrl
,
to
.
path
)
return
x
.
menuUrl
==
to
.
path
return
x
.
menuUrl
==
to
.
path
})
})
console
.
log
(
authMenu
)
if
(
authMenu
!=
-
1
)
{
if
(
authMenu
!=
-
1
)
{
next
({
next
({
...
to
,
...
to
,
...
...
src/components/common/verifyCode.vue
0 → 100644
View file @
64ac1237
<
template
>
<form
autocorrect=
"off"
autocapitalize=
"off"
autocomplete=
"off"
spellcheck=
"false"
>
<div
class=
"row justify-between"
>
<div
v-for=
"(x, i) in formatStyle.col"
:key=
"i"
class=
"override-verfity-ipt"
style=
"width: 60px"
>
<q-input
standout
style=
"height: 60px"
v-model=
"formatStyle.col[i]"
@
focus=
"codeFocus($event)"
:ref=
"setRef"
@
keyup=
"changFocus($event, i)"
maxlength=
"1"
mask=
"#"
dense
/>
</div>
<div
class=
"q-my-md negative f12"
v-if=
"hasError"
>
{{
errorMsg
}}
</div>
</div>
</form>
</
template
>
<
script
>
import
{
reactive
,
ref
}
from
'vue'
export
default
{
props
:
{
/**
* @description 请传入能够被12整除的整数
*/
digit
:
Number
,
/**
* @description 提示语
*/
hint
:
String
,
/**
* @description 绑定值
*/
modelValue
:
[
String
,
Number
]
},
setup
(
props
,
context
)
{
const
cols
=
reactive
([])
const
hasError
=
ref
(
false
)
const
errorMsg
=
ref
(
''
)
for
(
let
i
=
0
;
i
<
props
.
digit
;
i
++
)
{
cols
.
push
(
ref
(
''
))
}
const
formatStyle
=
reactive
({
col
:
reactive
(
cols
),
colStyle
:
ref
(
`col-
${
12
/
props
.
digit
}
`
)
})
const
myRef
=
ref
([])
const
setRef
=
el
=>
{
myRef
.
value
.
push
(
el
)
}
const
changFocus
=
(
event
,
index
)
=>
{
if
(
event
.
key
==
'Backspace'
)
{
if
(
index
!=
0
)
{
myRef
.
value
[
index
-
1
].
focus
()
}
}
else
if
(
index
<
props
.
digit
)
{
console
.
log
(
cols
[
index
])
if
(
formatStyle
.
col
[
index
]
!=
''
)
{
myRef
.
value
[
index
+
1
].
focus
()
}
}
updateValue
()
}
const
updateValue
=
()
=>
{
let
tempValue
=
ref
(
''
)
formatStyle
.
col
.
forEach
(
x
=>
{
tempValue
.
value
+=
x
.
toString
()
})
context
.
emit
(
'update:modelValue'
,
tempValue
.
value
)
}
const
codeFocus
=
e
=>
{
e
.
target
.
select
()
}
const
validate
=
()
=>
{
if
(
props
.
modelValue
.
length
!=
formatStyle
.
col
.
length
)
{
errorMsg
.
value
=
'请输入正确的验证码'
hasError
.
value
=
true
}
else
{
errorMsg
.
value
=
''
hasError
.
value
=
false
}
}
return
{
formatStyle
,
changFocus
,
setRef
,
codeFocus
,
validate
,
hasError
,
errorMsg
}
}
}
</
script
>
<
style
>
.override-verfity-ipt
.q-field--dense
.q-field__control
,
.override-verfity-ipt
.q-field--dense
.q-field__marginal
{
height
:
60px
!important
;
text-align
:
center
;
font-family
:
din
;
font-size
:
32px
;
}
.override-verfity-ipt
.q-field--dense
.q-field__control
input
,
.override-verfity-ipt
.q-field--dense
.q-field__marginal
input
{
text-align
:
center
;
}
</
style
>
src/config/app.ts
View file @
64ac1237
...
@@ -2,9 +2,10 @@
...
@@ -2,9 +2,10 @@
import
{
Notify
}
from
'quasar'
import
{
Notify
}
from
'quasar'
const
AppConfig
=
{
const
AppConfig
=
{
$message
:
Notify
$message
:
Notify
}
}
const
StaticConfig
=
{
const
StaticConfig
=
{
MaxPageSize
:
1000
MaxPageSize
:
1000
,
appsuffix
:
'大水豚渠道管理系统'
}
}
export
{
AppConfig
,
StaticConfig
}
export
{
AppConfig
,
StaticConfig
}
src/config/dictionary.ts
View file @
64ac1237
...
@@ -3,7 +3,8 @@
...
@@ -3,7 +3,8 @@
*/
*/
const
userDictionmary
=
{
const
userDictionmary
=
{
token
:
'access_token'
,
token
:
'access_token'
,
serverTokenName
:
'Token'
serverTokenName
:
'Token'
,
sendCodeTimeSpan
:
'scts'
}
}
export
{
userDictionmary
}
export
{
userDictionmary
}
src/css/font.sass
View file @
64ac1237
...
@@ -13,7 +13,7 @@
...
@@ -13,7 +13,7 @@
@font-face
@font-face
// 微软雅黑极细字体
// 微软雅黑极细字体
font-family
:
'msl'
font-family
:
'msl'
src
:
url('../assets/fonts/
PingFangBold
.ttf')
format
(
'truetype'
)
src
:
url('../assets/fonts/
MicrosoftYaHeiUISemilight
.ttf')
format
(
'truetype'
)
font-weight
:
normal
font-weight
:
normal
font-style
:
normal
font-style
:
normal
@font-face
@font-face
...
@@ -47,3 +47,9 @@ body
...
@@ -47,3 +47,9 @@ body
color
:
var
(
--
q-dark
)
color
:
var
(
--
q-dark
)
.change-a-primary
:hover
.change-a-primary
:hover
color
:
var
(
--
q-primary
)
color
:
var
(
--
q-primary
)
.f12
font-family
:
'msl'
!
important
font-size
:
13px
.mycard
box-shadow
:
0
0
.5rem
1
.5rem
0
.5rem
rgba
(
0
,
0
,
0
,
0
.075
)
!
important
border-radius
:
0
.475rem
!
important
src/module/meta/metaModule.ts
0 → 100644
View file @
64ac1237
import
{
StaticConfig
}
from
'@/config/app'
import
{
useMeta
}
from
'quasar'
import
{
ref
}
from
'vue'
const
userMetaTitleModule
=
()
=>
{
const
title
=
ref
(
StaticConfig
.
appsuffix
)
useMeta
(()
=>
{
return
{
title
:
title
.
value
}
})
const
setTitle
=
(
pageTitle
:
string
,
suffix
=
true
)
=>
{
if
(
suffix
)
{
title
.
value
=
`
${
pageTitle
}
-
${
StaticConfig
.
appsuffix
}
`
}
else
{
title
.
value
=
pageTitle
}
}
return
{
setTitle
}
}
export
default
userMetaTitleModule
src/module/scrollbar/scrollModule.ts
0 → 100644
View file @
64ac1237
import
{
reactive
}
from
'vue'
const
useScrollModule
=
()
=>
{
const
thumbStyle
=
reactive
({
right
:
'2px'
,
borderRadius
:
'5px'
,
backgroundColor
:
'#80C5C5'
,
width
:
'5px'
,
opacity
:
0.75
})
const
barStyle
=
reactive
({
right
:
'0px'
,
borderRadius
:
'9px'
,
backgroundColor
:
'#04c8c8'
,
width
:
'9px'
,
opacity
:
0.2
})
const
scrollStyle
=
reactive
({
thumbStyle
,
barStyle
})
return
{
scrollStyle
}
}
export
default
useScrollModule
\ No newline at end of file
src/module/user/loginModule.ts
View file @
64ac1237
import
{
ResultType
}
from
'@/@types/enumHelper'
import
router
from
'@/router'
import
{
UserActionsType
}
from
'@/store/modules/user/actions'
import
{
UserGetter
}
from
'@/store/modules/user/getters'
import
{
dispatchAction
,
getStoreGetter
,
setStoreState
}
from
'@/store/utils'
import
message
from
'@/utils/message'
import
message
from
'@/utils/message'
import
{
reactive
,
ref
}
from
'vue'
import
{
reactive
,
ref
}
from
'vue'
interface
LoginParams
{
interface
LoginParams
{
username
:
string
username
:
string
password
:
string
password
:
string
...
@@ -17,23 +22,63 @@ const userUserLoginModule = () => {
...
@@ -17,23 +22,63 @@ const userUserLoginModule = () => {
usernameRule
:
[(
val
:
any
)
=>
!!
val
||
'请填写账户信息'
],
usernameRule
:
[(
val
:
any
)
=>
!!
val
||
'请填写账户信息'
],
userpasswordRule
:
[(
val
:
any
)
=>
!!
val
||
'请填写密码信息'
]
userpasswordRule
:
[(
val
:
any
)
=>
!!
val
||
'请填写密码信息'
]
})
})
const
stateManager
=
reactive
({
const
usernameRef
=
ref
(
null
)
subLogin
:
ref
(
false
)
const
passwordRef
=
ref
(
null
)
})
const
usernameRef
=
ref
(
null
)
const
passwordRef
=
ref
(
null
)
const
loginSubmit
=
()
=>
{
const
loginSubmit
=
()
=>
{
const
ur
=
(
usernameRef
as
any
)
//断言任意类型
if
(
!
stateManager
.
subLogin
)
{
const
pr
=
(
passwordRef
as
any
)
stateManager
.
subLogin
=
true
ur
.
value
.
validate
()
const
ur
=
usernameRef
as
any
//断言任意类型
pr
.
value
.
validate
()
const
pr
=
passwordRef
as
any
if
(
ur
.
value
.
hasError
||
pr
.
value
.
hasError
)
{
ur
.
value
.
validate
()
message
.
warnMsg
(
'请完善登录信息'
)
pr
.
value
.
validate
()
}
else
{
if
(
ur
.
value
.
hasError
||
pr
.
value
.
hasError
)
{
message
.
successMsg
(
'验证通过'
)
message
.
warnMsg
(
'请完善登录信息'
)
stateManager
.
subLogin
=
false
}
else
{
setTimeout
(()
=>
{
//#region 测试使用
const
param
=
{
username
:
userModel
.
username
,
password
:
userModel
.
password
}
dispatchAction
<
UserActionsType
>
(
'user'
,
'userLogin'
,
param
)
const
menu
:
any
=
{
menuId
:
1
,
menuName
:
'首页'
,
menuUrl
:
'/index'
}
const
menu2
:
any
=
{
menuId
:
2
,
menuName
:
'首页'
,
menuUrl
:
'/'
}
const
menus
:
Array
<
any
>
=
[]
const
auths
=
getStoreGetter
<
UserGetter
>
(
'user'
,
'getUserAllAuth'
)
if
(
auths
!=
ResultType
.
EmptyArray
)
{
Object
.
assign
(
menus
,
...
auths
)
}
menus
.
push
(
menu
)
menus
.
push
(
menu2
)
setStoreState
(
'user'
,
'menuList'
,
menus
)
message
.
successMsg
(
'登录成功'
)
stateManager
.
subLogin
=
false
router
.
push
({
path
:
'/index'
})
//#endregion
},
2000
)
}
}
}
}
}
return
{
userModel
,
usernameRef
,
passwordRef
,
userValidateRule
,
loginSubmit
}
return
{
userModel
,
usernameRef
,
passwordRef
,
userValidateRule
,
loginSubmit
,
stateManager
}
}
}
export
default
userUserLoginModule
export
default
userUserLoginModule
src/module/user/registModule.ts
0 → 100644
View file @
64ac1237
import
{
AuthMenuType
}
from
'@/@types'
import
{
IndustryType
,
ResultType
,
ScaleType
}
from
'@/@types/enumHelper'
import
{
userDictionmary
}
from
'@/config/dictionary'
import
router
from
'@/router'
import
{
UserGetter
}
from
'@/store/modules/user/getters'
import
{
getStoreGetter
,
setStoreState
}
from
'@/store/utils'
import
message
from
'@/utils/message'
import
{
formatEnum
}
from
'@/utils/tools'
import
{
SessionStorage
}
from
'quasar'
// import message from '@/utils/message'
import
{
nextTick
,
reactive
,
ref
}
from
'vue'
interface
RegistParams
{
mobile
:
string
verfityCode
:
string
companyName
:
string
username
:
string
industry
:
number
scale
:
number
password
:
string
confirmPwd
:
string
}
const
useUserRegistModule
=
()
=>
{
const
userModel
:
RegistParams
=
reactive
({
mobile
:
ref
(
''
),
verfityCode
:
ref
(
''
),
companyName
:
ref
(
''
),
username
:
ref
(
''
),
industry
:
ref
(
0
),
scale
:
ref
(
0
),
password
:
ref
(
''
),
confirmPwd
:
ref
(
''
)
})
const
userRule
=
reactive
({
mobileRule
:
[(
val
:
any
)
=>
!!
/^1
(
3|4|5|6|7|8|9
)\d{9}
$/
.
test
(
val
)
||
'请填写你的手机账号信息'
],
verfityCodeRule
:
[(
val
:
any
)
=>
val
.
length
!=
6
||
'请填写验证码信息'
],
passwordRule
:
[(
val
:
any
)
=>
(
val
.
length
>=
6
&&
val
.
length
<=
30
)
||
'请输入6-30位密码'
],
confirmPwdRule
:
[(
val
:
any
)
=>
val
==
userModel
.
password
||
'两次密码不一致'
],
companyNameRule
:
[(
val
:
any
)
=>
!!
val
||
'请您填写企业名称'
],
usernameRule
:
[(
val
:
any
)
=>
!!
val
||
'请您填写联系人名称'
],
industryRule
:
[(
val
:
any
)
=>
val
!=
0
||
'请选择企业所属行业'
],
scaleRule
:
[(
val
:
any
)
=>
val
!=
0
||
'请选择'
]
})
const
stateManager
=
reactive
({
sendCodeStatus
:
ref
(
0
),
validateRules
:
ref
([]),
countDown
:
ref
(
0
),
timeProvide
:
ref
(),
canSubmitSetupOne
:
ref
(
true
),
subCode
:
ref
(
false
),
subSetupOne
:
ref
(
false
),
isSended
:
ref
(
false
),
verifyCodeLength
:
ref
(
6
),
currentSetup
:
ref
(
'1'
),
induArray
:
ref
(
formatEnum
(
IndustryType
)),
scaleArray
:
ref
(
formatEnum
(
ScaleType
)),
subRegist
:
ref
(
false
)
})
const
validateSendStatus
=
()
=>
{
if
(
stateManager
.
sendCodeStatus
==
2
)
return
const
mr
=
stateManager
.
validateRules
[
0
]
as
any
nextTick
(()
=>
{
stateManager
.
sendCodeStatus
=
mr
.
hasError
?
0
:
1
})
}
const
setValidateRules
=
(
el
:
HTMLElement
)
=>
{
(
stateManager
.
validateRules
as
Array
<
HTMLElement
>
).
push
(
el
)
}
const
checkCodeStatus
=
()
=>
{
if
(
SessionStorage
.
has
(
userDictionmary
.
sendCodeTimeSpan
))
{
const
oldSend
=
SessionStorage
.
getItem
<
number
>
(
userDictionmary
.
sendCodeTimeSpan
)
??
0
const
cnt
=
Math
.
abs
(
oldSend
-
Date
.
parse
(
new
Date
().
toString
()))
/
1000
if
(
cnt
>=
60
)
{
SessionStorage
.
remove
(
userDictionmary
.
sendCodeTimeSpan
)
stateManager
.
countDown
=
0
stateManager
.
sendCodeStatus
=
0
validateSendStatus
()
}
else
{
stateManager
.
countDown
=
60
-
cnt
stateManager
.
sendCodeStatus
=
2
stateManager
.
timeProvide
=
setInterval
(
beginCutDown
,
1000
)
}
}
}
const
sendCode
=
()
=>
{
if
(
!
stateManager
.
subCode
&&
stateManager
.
countDown
==
0
&&
stateManager
.
sendCodeStatus
==
1
)
{
stateManager
.
subCode
=
true
//TODO: 完成接口调用
setTimeout
(()
=>
{
stateManager
.
isSended
=
true
stateManager
.
countDown
=
60
stateManager
.
sendCodeStatus
=
2
SessionStorage
.
set
(
userDictionmary
.
sendCodeTimeSpan
,
Date
.
parse
(
new
Date
().
toString
()))
stateManager
.
subCode
=
false
stateManager
.
timeProvide
=
setInterval
(
beginCutDown
,
1000
)
},
3000
)
}
}
const
beginCutDown
=
()
=>
{
stateManager
.
countDown
--
if
(
stateManager
.
countDown
==
0
)
{
SessionStorage
.
remove
(
userDictionmary
.
sendCodeTimeSpan
)
stateManager
.
sendCodeStatus
=
0
validateSendStatus
()
if
(
stateManager
.
timeProvide
)
{
clearInterval
(
stateManager
.
timeProvide
)
stateManager
.
timeProvide
=
null
}
}
}
const
submitValidateCode
=
()
=>
{
if
(
!
stateManager
.
subSetupOne
)
{
stateManager
.
subSetupOne
=
true
let
isError
=
false
for
(
let
i
=
0
;
i
<
stateManager
.
validateRules
.
length
;
i
++
)
{
const
mr
=
stateManager
.
validateRules
[
i
]
as
any
if
(
mr
){
mr
.
validate
()
}
}
for
(
let
i
=
0
;
i
<
stateManager
.
validateRules
.
length
;
i
++
)
{
const
mr
=
stateManager
.
validateRules
[
i
]
as
any
if
(
mr
&&
mr
.
hasError
)
{
isError
=
true
break
}
}
if
(
!
isError
&&
userModel
.
verfityCode
.
length
==
stateManager
.
verifyCodeLength
&&
stateManager
.
isSended
)
{
setTimeout
(()
=>
{
stateManager
.
subSetupOne
=
false
if
(
userModel
.
verfityCode
==
'888888'
)
{
stateManager
.
currentSetup
=
'2'
stateManager
.
isSended
=
false
}
else
{
message
.
warnMsg
(
'验证码错误,请重新输入'
)
}
},
3000
)
}
else
{
stateManager
.
subSetupOne
=
false
}
}
}
const
doRegist
=
()
=>
{
if
(
!
stateManager
.
subRegist
)
{
stateManager
.
subRegist
=
true
let
isError
=
false
for
(
let
i
=
0
;
i
<
stateManager
.
validateRules
.
length
;
i
++
)
{
const
mr
=
stateManager
.
validateRules
[
i
]
as
any
if
(
mr
){
mr
.
validate
()
}
}
for
(
let
i
=
0
;
i
<
stateManager
.
validateRules
.
length
;
i
++
)
{
const
mr
=
stateManager
.
validateRules
[
i
]
as
any
if
(
mr
&&
mr
.
hasError
)
{
isError
=
true
break
}
}
if
(
isError
)
{
stateManager
.
subRegist
=
false
}
else
{
console
.
log
(
userModel
)
//TODO: 调用注册接口
setTimeout
(()
=>
{
//注册成功应该实现自动登录,让后跳转到首页
const
dissmiss
=
message
.
loadMsg
(
'注册成功,正常初始化系统,马上就好'
)
setTimeout
(()
=>
{
dissmiss
()
message
.
successMsg
(
'初始化成功,正在进入系统'
)
//#region 测试使用
const
menu
:
AuthMenuType
=
{
menuId
:
1
,
menuName
:
'首页'
,
menuUrl
:
'/index'
}
const
menus
=
new
Array
<
AuthMenuType
>
()
const
auths
=
getStoreGetter
<
UserGetter
>
(
'user'
,
'getUserAllAuth'
)
if
(
auths
!=
ResultType
.
EmptyArray
)
{
Object
.
assign
(
menus
,
...
auths
)
}
menus
.
push
(
menu
)
setStoreState
(
'user'
,
'menuList'
,
menus
)
router
.
push
({
path
:
'/index'
})
//#endregion
},
2000
)
},
3000
)
}
}
}
return
{
userModel
,
setValidateRules
,
userRule
,
stateManager
,
validateSendStatus
,
checkCodeStatus
,
sendCode
,
submitValidateCode
,
doRegist
}
}
export
default
useUserRegistModule
src/pages/Index.vue
View file @
64ac1237
<
template
>
<
template
>
<q-page
class=
"row items-center justify-evenly"
>
<q-page
class=
"row items-center justify-evenly"
>
<example-component
<example-component
title=
"Example component"
active
:todos=
"todos"
:meta=
"meta"
></example-component>
title=
"Example component"
active
:todos=
"todos"
:meta=
"meta"
></example-component>
</q-page>
</q-page>
</
template
>
</
template
>
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
{
Todo
,
Meta
}
from
'@/components/models'
;
import
{
Todo
,
Meta
}
from
'@/components/models'
import
ExampleComponent
from
'components/CompositionComponent.vue'
;
import
ExampleComponent
from
'components/CompositionComponent.vue'
import
{
defineComponent
,
ref
}
from
'vue'
;
import
{
defineComponent
,
ref
}
from
'vue'
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'PageIndex'
,
name
:
'PageIndex'
,
...
@@ -39,11 +34,11 @@ export default defineComponent({
...
@@ -39,11 +34,11 @@ export default defineComponent({
id
:
5
,
id
:
5
,
content
:
'ct5'
content
:
'ct5'
}
}
])
;
])
const
meta
=
ref
<
Meta
>
({
const
meta
=
ref
<
Meta
>
({
totalCount
:
1200
totalCount
:
1200
})
;
})
return
{
todos
,
meta
}
;
return
{
todos
,
meta
}
}
}
})
;
})
</
script
>
</
script
>
src/pages/auth/login.vue
View file @
64ac1237
...
@@ -2,10 +2,13 @@
...
@@ -2,10 +2,13 @@
<div
class=
"row"
>
<div
class=
"row"
>
<div
class=
"col window-height column"
>
<div
class=
"col window-height column"
>
<div
class=
"col q-pa-lg flex justify-center items-center"
>
<div
class=
"col q-pa-lg flex justify-center items-center"
>
<div>
<div
class=
"relative-position"
>
<img
src=
"../../assets/images/big-logo.png"
style=
"height: 60px"
class=
"q-mb-lg"
alt=
""
/>
<img
src=
"../../assets/images/big-logo.png"
style=
"height: 60px"
class=
"q-mb-lg"
alt=
""
/>
<div
class=
"text-h5 pfb q-mb-md"
>
欢迎回来,亲爱的用户
</div>
<div
class=
"text-h5 pfb q-mb-md"
>
欢迎回来,亲爱的用户
</div>
<div
class=
"pfb text-grey-5 text-subtitle"
>
通过配置您的推广渠道,实现对线索和客户的快速获取
<br
/>
并且及时的跟进
</div>
<div
class=
"pfb text-grey-5 text-subtitle"
>
通过配置您的推广渠道,实现对线索和客户的快速获取
<br
/>
并且及时的跟进
</div>
<div
class=
"absolute q-mt-md"
style=
"top: 0; left: 180px"
>
<q-badge
style=
"background: #cbcfe0"
floating
transparent
>
Alpha
</q-badge>
</div>
</div>
</div>
</div>
</div>
<div
class=
"col q-mb-lg login-bg"
></div>
<div
class=
"col q-mb-lg login-bg"
></div>
...
@@ -29,34 +32,41 @@
...
@@ -29,34 +32,41 @@
</div>
</div>
</div>
</div>
<div
class=
"q-mt-xs"
>
<div
class=
"q-mt-xs"
>
<q-input
standout
v-model=
"userModel.password"
dense
ref=
"passwordRef"
:rules=
"userValidateRule.userpasswordRule"
/>
<q-input
standout
v-model=
"userModel.password"
type=
"password"
dense
ref=
"passwordRef"
:rules=
"userValidateRule.userpasswordRule"
/>
</div>
</div>
<div
class=
"q-mt-md"
>
<div
class=
"q-mt-md"
>
<q-checkbox
dense
v-model=
"userModel.remeber"
label=
"30天免登录"
color=
"accent"
/>
<q-checkbox
dense
v-model=
"userModel.remeber"
label=
"30天免登录"
color=
"accent"
/>
</div>
</div>
<div
class=
"q-mt-lg text-center"
>
<div
class=
"q-mt-lg text-center"
>
<q-btn
class=
"pfb"
color=
"primary"
unelevated
label=
"登 录"
style=
"width: 10rem"
@
click=
"loginSubmit"
></q-btn>
<q-btn
class=
"pfb"
color=
"primary"
:loading=
"stateManager.subLogin"
unelevated
label=
"登 录"
style=
"width: 10rem"
@
click=
"loginSubmit"
></q-btn>
</div>
</div>
</q-card>
</q-card>
</div>
</div>
<div
class=
"q-my-lg q-mx-xl text-center w-450-only"
>
<div
class=
"q-my-lg q-mx-xl text-center row w-450-only"
>
<router-link
:to=
"
{ path: '/auth/forget' }" class="pfb text-body no-underline change-a-primary q-mr-md">关于大水豚
</router-link>
<div
class=
"f12 text-dark"
>
© 2021-
{{
dtNow
}}
微途科技 版权所有
</div>
<router-link
:to=
"
{ path: '/auth/forget' }" class="pfb text-body no-underline change-a-primary q-mr-md">联系我们
</router-link>
<div
class=
"text-center col text-right"
>
<router-link
:to=
"
{ path: '/auth/forget' }" class="pfb text-body no-underline change-a-primary q-mr-md">技术支持
</router-link>
<router-link
:to=
"
{ path: '/auth/forget' }" class="f12 no-underline change-a-primary q-mr-md">关于大水豚
</router-link>
<router-link
:to=
"
{ path: '/auth/forget' }" class="f12 no-underline change-a-primary q-mr-md">联系我们
</router-link>
<router-link
:to=
"
{ path: '/auth/forget' }" class="f12 no-underline change-a-primary q-mr-md">技术支持
</router-link>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
<
script
>
<
script
>
import
{
defineComponent
,
ref
}
from
'vue'
import
{
defineComponent
}
from
'vue'
import
useLgoinModule
from
'@/module/user/loginModule'
import
useLgoinModule
from
'@/module/user/loginModule'
import
useMetaModule
from
'@/module/meta/metaModule'
export
default
defineComponent
({
export
default
defineComponent
({
setup
()
{
setup
()
{
let
{
userModel
,
usernameRef
,
passwordRef
,
userValidateRule
,
loginSubmit
}
=
useLgoinModule
()
//TODO: 缺陷,验证与提交应该使用Form表单来完成,不应该进行单个验证
let
{
userModel
,
usernameRef
,
passwordRef
,
userValidateRule
,
loginSubmit
,
stateManager
}
=
useLgoinModule
()
return
{
userModel
,
usernameRef
,
passwordRef
,
userValidateRule
,
loginSubmit
}
let
{
setTitle
}
=
useMetaModule
()
setTitle
(
'登录'
)
const
dtNow
=
new
Date
().
getFullYear
()
return
{
userModel
,
usernameRef
,
passwordRef
,
userValidateRule
,
loginSubmit
,
dtNow
,
stateManager
}
}
}
})
})
</
script
>
</
script
>
...
@@ -74,7 +84,7 @@ export default defineComponent({
...
@@ -74,7 +84,7 @@ export default defineComponent({
box-shadow
:
0
0.5rem
1.5rem
0.5rem
rgba
(
0
,
0
,
0
,
0.075
)
!important
;
box-shadow
:
0
0.5rem
1.5rem
0.5rem
rgba
(
0
,
0
,
0
,
0.075
)
!important
;
border-radius
:
0.475rem
!important
;
border-radius
:
0.475rem
!important
;
}
}
.w-450-only
{
.w-450-only
{
width
:
450px
;
width
:
450px
;
}
}
</
style
>
</
style
>
src/pages/auth/regist.vue
0 → 100644
View file @
64ac1237
<
template
>
<div
class=
"window-height regist-box column"
>
<q-scroll-area
:thumb-style=
"scrollStyle.thumbStyle"
:bar-style=
"scrollStyle.barStyle"
class=
"full-height full-width"
>
<div
class=
"w-600 col q-py-lg flex items-center"
>
<div
class=
"form-box-diy col"
>
<div
class=
"text-center"
>
<img
src=
"@/assets/images/big-logo.png"
height=
"60"
alt=
""
/>
</div>
<q-card
class=
"mycard q-mt-lg q-pa-xl"
>
<q-tab-panels
v-model=
"stateManager.currentSetup"
animated
>
<q-tab-panel
name=
"1"
>
<div
class=
"text-h5 pfb q-mb-md text-center"
>
创建账号
</div>
<div
class=
"text-center q-mb-lg"
>
<span
class=
"text-grey-5 pfb text-subtitle"
>
已经有账号了?
</span>
<router-link
:to=
"
{ path: '/auth/login' }" class="text-primary pfb text-subtitle">点击登录
</router-link>
</div>
<div
class=
"text-body pfb"
>
手机号:
</div>
<div
class=
"q-mt-xs row"
>
<q-input
standout
v-model=
"userModel.mobile"
mask=
"###########"
class=
"col"
@
update:model-value=
"validateSendStatus"
dense
:ref=
"setValidateRules"
:rules=
"userRule.mobileRule"
/>
<div
class=
"q-ml-md"
>
<q-btn
color=
"accent"
:loading=
"stateManager.subCode"
class=
"btn-fixed-width-102 ellipsis"
:disable=
"stateManager.sendCodeStatus != 1"
unelevated
@
click=
"sendCode"
>
{{
stateManager
.
sendCodeStatus
!=
2
?
'发送验证码'
:
`${stateManager.countDown
}
秒后重发`
}}
<
/q-btn
>
<
/div
>
<
/div
>
<
div
class
=
"text-body pfb q-mt-md"
>
验证码:
<
/div
>
<
div
class
=
"q-mt-xs"
>
<
verifyCodeBox
:
digit
=
"stateManager.verifyCodeLength"
v
-
model
=
"userModel.verfityCode"
><
/verifyCodeBox
>
<
/div
>
<
div
class
=
"q-mt-md"
>
<
div
class
=
"col text-body pfb"
>
密码:
<
/div
>
<
/div
>
<
div
class
=
"q-mt-xs"
>
<
q
-
input
standout
v
-
model
=
"userModel.password"
type
=
"password"
dense
:
ref
=
"setValidateRules"
:
rules
=
"userRule.passwordRule"
/>
<
/div
>
<
div
class
=
"q-mt-md"
>
<
div
class
=
"col text-body pfb"
>
确认密码:
<
/div
>
<
/div
>
<
div
class
=
"q-mt-xs"
>
<
q
-
input
standout
v
-
model
=
"userModel.confirmPwd"
type
=
"password"
dense
:
ref
=
"setValidateRules"
:
rules
=
"userRule.confirmPwdRule"
/>
<
/div
>
<
div
class
=
"q-mt-md"
>
<
q
-
btn
:
loading
=
"stateManager.subSetupOne"
:
color
=
"stateManager.isSended && userModel.verfityCode.length == stateManager.verifyCodeLength ? 'primary' : 'secondary'"
class
=
"full-width"
:
disable
=
"!stateManager.isSended || userModel.verfityCode.length != 6"
unelevated
@
click
=
"submitValidateCode"
>
下一步
<
/q-btn
>
<
/div
>
<
/q-tab-panel
>
<
q
-
tab
-
panel
name
=
"2"
>
<
div
class
=
"text-h5 pfb q-mb-md text-center"
>
补充资料填写
<
/div
>
<
div
class
=
"text-body pfb"
>
注册账号:
<
/div
>
<
div
class
=
"q-mt-xs din"
style
=
"font-size: 32px"
>
{{
userModel
.
mobile
==
''
?
'17308037817'
:
userModel
.
mobile
}}
<
/div
>
<
div
class
=
"q-mt-md"
>
<
div
class
=
"text-body pfb q-mt-md"
>
企业名称:
<
/div
>
<
/div
>
<
div
class
=
"q-mt-xs"
>
<
q
-
input
standout
v
-
model
=
"userModel.companyName"
dense
:
ref
=
"setValidateRules"
:
rules
=
"userRule.companyNameRule"
/>
<
/div
>
<
div
class
=
"text-body pfb q-mt-md"
>
姓名:
<
/div
>
<
div
class
=
"q-mt-xs"
>
<
q
-
input
standout
v
-
model
=
"userModel.username"
dense
:
ref
=
"setValidateRules"
:
rules
=
"userRule.usernameRule"
/>
<
/div
>
<
div
class
=
"text-body pfb q-mt-md"
>
联系人姓名:
<
/div
>
<
div
class
=
"q-mt-xs"
>
<
q
-
input
standout
v
-
model
=
"userModel.username"
dense
:
ref
=
"setValidateRules"
:
rules
=
"userRule.usernameRule"
/>
<
/div
>
<
div
class
=
"text-body pfb q-mt-md"
>
所属行业
<
/div
>
<
div
class
=
"q-mt-xs"
>
<
q
-
select
standout
dense
v
-
model
=
"userModel.industry"
:
ref
=
"setValidateRules"
:
options
=
"stateManager.induArray"
option
-
label
=
"key"
:
rules
=
"userRule.industryRule"
behavior
=
"menu"
option
-
value
=
"value"
map
-
options
><
/q-select
>
<
/div
>
<
div
class
=
"text-body pfb q-mt-md"
>
企业规模
<
/div
>
<
div
class
=
"q-mt-xs"
>
<
q
-
select
standout
dense
v
-
model
=
"userModel.scale"
:
ref
=
"setValidateRules"
:
options
=
"stateManager.scaleArray"
option
-
label
=
"key"
:
rules
=
"userRule.scaleRule"
behavior
=
"menu"
option
-
value
=
"value"
map
-
options
><
/q-select
>
<
/div
>
<
div
class
=
"q-mt-lg text-center"
>
<
q
-
btn
class
=
"pfb"
color
=
"primary"
:
loading
=
"stateManager.subRegist"
unelevated
label
=
"立即注册"
style
=
"width: 10rem"
@
click
=
"doRegist"
><
/q-btn
>
<
/div
>
<
/q-tab-panel
>
<
/q-tab-panels
>
<
/q-card
>
<
/div
>
<
/div
>
<
/q-scroll-area
>
<
/div
>
<
/template
>
<
script
>
import
{
defineComponent
,
onMounted
}
from
'vue'
import
useMetaModule
from
'@/module/meta/metaModule'
import
useUserRegistModule
from
'@/module/user/registModule'
import
verifyCodeBox
from
'@/components/common/verifyCode.vue'
import
useScrollModule
from
'@/module/scrollbar/scrollModule'
export
default
defineComponent
({
components
:
{
verifyCodeBox
}
,
setup
()
{
let
{
setTitle
}
=
useMetaModule
()
setTitle
(
'创建账户'
)
let
{
userModel
,
setValidateRules
,
userRule
,
validateSendStatus
,
stateManager
,
sendCode
,
checkCodeStatus
,
submitValidateCode
,
doRegist
}
=
useUserRegistModule
()
let
{
scrollStyle
}
=
useScrollModule
()
onMounted
(()
=>
{
checkCodeStatus
()
}
)
return
{
userModel
,
userRule
,
setValidateRules
,
validateSendStatus
,
stateManager
,
sendCode
,
submitValidateCode
,
scrollStyle
,
doRegist
}
}
}
)
<
/script
>
<
style
>
.
regist
-
box
{
background
-
image
:
url
(..
/
..
/
assets
/
images
/
14
.
png
);
background
-
attachment
:
fixed
;
background
-
position
-
y
:
bottom
;
background
-
repeat
:
no
-
repeat
;
background
-
size
:
contain
;
}
.
btn
-
fixed
-
width
-
102
{
width
:
102
px
;
padding
:
7
px
14
px
;
}
.
w
-
600
{
width
:
600
px
;
margin
:
2
rem
auto
;
}
<
/style
>
src/router/routes.ts
View file @
64ac1237
...
@@ -2,14 +2,18 @@ import { RouteRecordRaw } from 'vue-router'
...
@@ -2,14 +2,18 @@ import { RouteRecordRaw } from 'vue-router'
const
routes
:
RouteRecordRaw
[]
=
[
const
routes
:
RouteRecordRaw
[]
=
[
{
{
path
:
'/'
,
path
:
'/
index
'
,
component
:
()
=>
import
(
'layouts/MainLayout.vue'
),
component
:
()
=>
import
(
'
@/
layouts/MainLayout.vue'
),
children
:
[{
path
:
''
,
component
:
()
=>
import
(
'pages/Index.vue'
)
}]
children
:
[{
path
:
''
,
component
:
()
=>
import
(
'
@/
pages/Index.vue'
)
}]
},
},
{
{
path
:
'/auth/login'
,
path
:
'/auth/login'
,
component
:
()
=>
import
(
'@/pages/auth/login.vue'
)
component
:
()
=>
import
(
'@/pages/auth/login.vue'
)
},
},
{
path
:
'/auth/regist'
,
component
:
()
=>
import
(
'@/pages/auth/regist.vue'
)
},
// Always leave this as last one,
// Always leave this as last one,
// but you can also remove it
// but you can also remove it
{
{
...
...
src/store/modules/user/actions.ts
View file @
64ac1237
...
@@ -7,23 +7,51 @@ import Store from '@/store'
...
@@ -7,23 +7,51 @@ import Store from '@/store'
*/
*/
const
userActions
=
{
const
userActions
=
{
// 刷新令牌
// 刷新令牌
refreshToken
()
{
refreshToken
()
{
return
UserService
.
refreshToken
({
return
UserService
.
refreshToken
({
// eslint-disable-next-line
// eslint-disable-next-line
refresh_token
:
Store
.
state
.
user
.
token
.
refresh_token
refresh_token
:
Store
.
state
.
user
.
token
.
refresh_token
}).
then
(
res
=>
{
}).
then
(
res
=>
{
// token过期时间
// token过期时间
const
expireTime
=
res
.
data
.
expires_in
*
1000
+
new
Date
().
getTime
()
const
expireTime
=
res
.
data
.
expires_in
*
1000
+
new
Date
().
getTime
()
setStoreState
(
'user'
,
'token'
,
{
...
res
.
data
,
expireTime
})
setStoreState
(
'user'
,
'token'
,
{
...
res
.
data
,
expireTime
})
})
})
},
},
// 获取用户信息
getUserDetail
()
{
// 获取用户信息
return
UserService
.
getUserDetail
().
then
(
res
=>
{
getUserDetail
()
{
setStoreState
(
'user'
,
'userDetail'
,
res
.
data
.
data
)
return
UserService
.
getUserDetail
().
then
(
res
=>
{
})
setStoreState
(
'user'
,
'userDetail'
,
res
.
data
.
data
)
}
})
},
userLogin
(
params
:
{
username
:
string
;
password
:
string
})
{
//TODO: 实现用户登录
// UserService.login(params).then(res=>{
// })
//测试伪造数据
const
loginUser
=
{
email
:
'alex9012@vip.qq.com'
,
type
:
0
,
// 用户账号本身类型 0:主账号,1:子账号
userId
:
1
,
username
:
params
.
username
,
description
:
''
,
nickName
:
'罗超'
,
phone
:
'17308037817'
,
tenantId
:
1
,
roleId
:
1
}
setStoreState
(
'user'
,
'userDetail'
,
loginUser
)
const
token
=
{
token_type
:
'login_auth'
,
access_token
:
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}
const
expireTime
=
60
*
72
*
1000
+
new
Date
().
getTime
()
setStoreState
(
'user'
,
'token'
,
{
...
token
,
expireTime
})
}
}
}
type
UserActionsType
=
typeof
userActions
type
UserActionsType
=
typeof
userActions
...
...
src/store/modules/user/getters.ts
View file @
64ac1237
import
{
ResultType
}
from
'@/@types'
import
{
ResultType
}
from
'@/@types
/enumHelper
'
import
store
from
'@/store'
import
store
from
'@/store'
const
userGetter
=
{
const
userGetter
=
{
...
@@ -7,7 +7,9 @@ const userGetter = {
...
@@ -7,7 +7,9 @@ const userGetter = {
return
token
.
access_token
??
ResultType
.
Empty
return
token
.
access_token
??
ResultType
.
Empty
},
},
getUserAllAuth
()
{
getUserAllAuth
()
{
return
store
.
state
.
user
.
menuList
const
menuList
:
any
[]
=
store
.
state
.
user
.
menuList
console
.
log
((
menuList
.
length
>
0
?
menuList
:
ResultType
.
EmptyArray
),
menuList
.
length
,
menuList
)
return
menuList
.
length
>
0
?
menuList
:
ResultType
.
EmptyArray
}
}
}
}
...
...
src/store/modules/user/state.ts
View file @
64ac1237
import
{
AuthMenuType
,
StateType
}
from
'@/@types'
import
{
StateType
}
from
'@/@types'
import
{
Module
}
from
'vuex'
import
{
Module
}
from
'vuex'
import
ModuleTeam
from
'./modules/team/state'
import
ModuleTeam
from
'./modules/team/state'
interface
Token
{
interface
Token
{
...
@@ -19,7 +19,7 @@ const state = {
...
@@ -19,7 +19,7 @@ const state = {
},
},
currentTeamRoleId
:
0
,
// 当前所选择的团队用户所具有的权限
currentTeamRoleId
:
0
,
// 当前所选择的团队用户所具有的权限
currentProjectRoleId
:
0
,
// 当前所选择的项目用户所具有的权限
currentProjectRoleId
:
0
,
// 当前所选择的项目用户所具有的权限
menuList
:
[]
as
Array
<
AuthMenuType
>
menuList
:
[]
}
}
type
UserStateType
=
typeof
state
type
UserStateType
=
typeof
state
...
...
src/utils/auth.ts
View file @
64ac1237
import
{
getStoreGetter
}
from
'@/store/utils'
import
{
getStoreGetter
}
from
'@/store/utils'
import
{
UserGetter
}
from
'@/store/modules/user/getters'
import
{
UserGetter
}
from
'@/store/modules/user/getters'
import
{
ResultType
}
from
'@/@types'
import
{
ResultType
}
from
'@/@types
/enumHelper
'
/**
/**
* @description 获取授权信息
* @description 获取授权信息
...
@@ -16,5 +16,6 @@ export function getAuth() {
...
@@ -16,5 +16,6 @@ export function getAuth() {
*/
*/
export
function
getUserAllMenu
()
{
export
function
getUserAllMenu
()
{
const
auths
=
getStoreGetter
<
UserGetter
>
(
'user'
,
'getUserAllAuth'
)
const
auths
=
getStoreGetter
<
UserGetter
>
(
'user'
,
'getUserAllAuth'
)
console
.
log
(
auths
)
return
auths
.
length
>
0
?
auths
:
ResultType
.
EmptyArray
return
auths
.
length
>
0
?
auths
:
ResultType
.
EmptyArray
}
}
src/utils/message.ts
View file @
64ac1237
import
{
Notify
}
from
'quasar'
import
{
Notify
,
QSpinnerIos
}
from
'quasar'
const
message
=
{
const
message
=
{
warnMsg
:
(
msg
:
string
)
=>
{
warnMsg
:
(
msg
:
string
)
=>
{
...
@@ -6,16 +6,35 @@ const message = {
...
@@ -6,16 +6,35 @@ const message = {
message
:
msg
,
message
:
msg
,
color
:
'warning'
,
color
:
'warning'
,
textColor
:
'dark'
,
textColor
:
'dark'
,
position
:
'top'
,
icon
:
'announcement'
icon
:
'announcement'
})
})
},
},
errorMsg
:
(
msg
:
string
)
=>
{
Notify
.
create
({
message
:
msg
,
type
:
'negative'
,
position
:
'top'
})
},
successMsg
:
(
msg
:
string
)
=>
{
successMsg
:
(
msg
:
string
)
=>
{
Notify
.
create
({
Notify
.
create
({
message
:
msg
,
message
:
msg
,
color
:
'positive'
,
color
:
'positive'
,
position
:
'top'
,
textColor
:
'white'
,
textColor
:
'white'
,
icon
:
'success'
icon
:
'check'
})
},
loadMsg
:
(
msg
:
string
):
any
=>
{
const
loadDissmiss
=
Notify
.
create
({
message
:
msg
,
color
:
'secondary'
,
position
:
'center'
,
textColor
:
'dark'
,
spinner
:
QSpinnerIos
})
})
return
loadDissmiss
}
}
}
}
...
...
src/utils/tools.ts
View file @
64ac1237
/**
/**
* @description 按照需要写入 必要可以注入全局
* @description 按照需要写入 必要可以注入全局
*/
*/
interface
enumObj
{
key
:
string
value
:
number
}
/**
* @description 将枚举转为数组
* @param objEnum 枚举对象
* @returns 转化后的数组
*/
export
function
formatEnum
(
objEnum
:
any
):
Array
<
enumObj
>
{
const
array
:
Array
<
enumObj
>
=
new
Array
<
enumObj
>
()
for
(
const
key
in
objEnum
)
{
if
(
!
isNaNModified
(
key
))
continue
const
tempEnumObj
:
enumObj
=
{
key
,
value
:
objEnum
[
key
]
as
number
}
array
.
push
(
tempEnumObj
)
}
return
array
}
export
function
isNaNModified
(
inputStr
:
string
)
{
const
numericRepr
=
parseFloat
(
inputStr
)
return
isNaN
(
numericRepr
)
||
numericRepr
.
toString
().
length
!=
inputStr
.
length
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment