Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
intelligent_qp_manager
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
张伯涛
intelligent_qp_manager
Commits
e622c0a2
Commit
e622c0a2
authored
Oct 17, 2024
by
张伯涛
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
用户管理初步调整
parent
71a8ead4
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
452 additions
and
9 deletions
+452
-9
system.ts
src/api/demo/system.ts
+1
-1
componentSetting.ts
src/settings/componentSetting.ts
+1
-1
index.ts
src/utils/http/axios/index.ts
+2
-0
LoginForm.vue
src/views/sys/login/LoginForm.vue
+2
-0
AccountDetail.vue
src/views/system/user/AccountDetail.vue
+61
-0
AccountModal.vue
src/views/system/user/AccountModal.vue
+69
-0
DeptTree.vue
src/views/system/user/DeptTree.vue
+38
-0
account.data.ts
src/views/system/user/account.data.ts
+158
-0
index.vue
src/views/system/user/index.vue
+120
-7
No files found.
src/api/demo/system.ts
View file @
e622c0a2
...
...
@@ -13,7 +13,7 @@ import {
import
{
defHttp
}
from
'@/utils/http/axios'
;
enum
Api
{
AccountList
=
'/system/
getAccountL
ist'
,
AccountList
=
'/system/
user/l
ist'
,
IsAccountExist
=
'/system/accountExist'
,
DeptList
=
'/system/getDeptList'
,
setRoleStatus
=
'/system/setRoleStatus'
,
...
...
src/settings/componentSetting.ts
View file @
e622c0a2
...
...
@@ -13,7 +13,7 @@ export default {
// The number field name of each page displayed in the background
sizeField
:
'pageSize'
,
// Field name of the form data returned by the interface
listField
:
'
item
s'
,
listField
:
'
row
s'
,
// Total number of tables returned by the interface field name
totalField
:
'total'
,
},
...
...
src/utils/http/axios/index.ts
View file @
e622c0a2
...
...
@@ -167,6 +167,7 @@ const transform: AxiosTransform = {
* @description: 响应拦截器处理
*/
responseInterceptors
:
(
res
:
AxiosResponse
<
any
>
)
=>
{
console
.
log
(
'ree'
,
res
)
return
res
;
},
...
...
@@ -174,6 +175,7 @@ const transform: AxiosTransform = {
* @description: 响应错误处理
*/
responseInterceptorsCatch
:
(
axiosInstance
:
AxiosInstance
,
error
:
any
)
=>
{
console
.
log
(
'3333333333333333'
,
error
)
const
{
t
}
=
useI18n
();
const
errorLogStore
=
useErrorLogStoreWithOut
();
errorLogStore
.
addAjaxErrorInfo
(
error
);
...
...
src/views/sys/login/LoginForm.vue
View file @
e622c0a2
...
...
@@ -139,6 +139,7 @@
username
:
data
.
account
,
mode
:
'none'
,
//不要默认的错误提示
});
console
.
log
(
'userInfo'
,
userInfo
)
if
(
userInfo
)
{
notification
.
success
({
message
:
t
(
'sys.login.loginSuccessTitle'
),
...
...
@@ -147,6 +148,7 @@
});
}
}
catch
(
error
)
{
console
.
log
(
'error'
,
error
)
createErrorModal
({
title
:
t
(
'sys.api.errorTip'
),
content
:
(
error
as
unknown
as
Error
).
message
||
t
(
'sys.api.networkExceptionMsg'
),
...
...
src/views/system/user/AccountDetail.vue
0 → 100644
View file @
e622c0a2
<
template
>
<PageWrapper
:title=
"`用户` + userId + `的资料`"
content=
"这是用户资料详情页面。本页面仅用于演示相同路由在tab中打开多个页面并且显示不同的数据"
contentBackground
@
back=
"goBack"
>
<template
#
extra
>
<a-button
type=
"primary"
danger
>
禁用账号
</a-button>
<a-button
type=
"primary"
>
修改密码
</a-button>
</
template
>
<
template
#
footer
>
<a-tabs
default-active-key=
"detail"
v-model:activeKey=
"currentKey"
>
<a-tab-pane
key=
"detail"
tab=
"用户资料"
/>
<a-tab-pane
key=
"logs"
tab=
"操作日志"
/>
</a-tabs>
</
template
>
<div
class=
"pt-4 m-4 desc-wrap"
>
<
template
v-if=
"currentKey == 'detail'"
>
<div
v-for=
"i in 10"
:key=
"i"
>
这是用户
{{
userId
}}
资料Tab
</div>
</
template
>
<
template
v-if=
"currentKey == 'logs'"
>
<div
v-for=
"i in 10"
:key=
"i"
>
这是用户
{{
userId
}}
操作日志Tab
</div>
</
template
>
</div>
</PageWrapper>
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
}
from
'vue'
;
import
{
useRoute
}
from
'vue-router'
;
import
{
PageWrapper
}
from
'@/components/Page'
;
import
{
useGo
}
from
'@/hooks/web/usePage'
;
import
{
useTabs
}
from
'@/hooks/web/useTabs'
;
import
{
Tabs
}
from
'ant-design-vue'
;
defineOptions
({
name
:
'AccountDetail'
});
const
ATabs
=
Tabs
;
const
ATabPane
=
Tabs
.
TabPane
;
const
route
=
useRoute
();
const
go
=
useGo
();
// 此处可以得到用户ID
const
userId
=
ref
(
route
.
params
?.
id
);
const
currentKey
=
ref
(
'detail'
);
const
{
setTitle
}
=
useTabs
();
// TODO
// 本页代码仅作演示,实际应当通过userId从接口获得用户的相关资料
// 设置Tab的标题(不会影响页面标题)
setTitle
(
'详情:用户'
+
userId
.
value
);
// 页面左侧点击返回链接时的操作
function
goBack
()
{
// 本例的效果时点击返回始终跳转到账号列表页,实际应用时可返回上一页
go
(
'/system/account'
);
}
</
script
>
<
style
></
style
>
src/views/system/user/AccountModal.vue
0 → 100644
View file @
e622c0a2
<
template
>
<BasicModal
v-bind=
"$attrs"
@
register=
"registerModal"
:title=
"getTitle"
@
ok=
"handleSubmit"
>
<BasicForm
@
register=
"registerForm"
/>
</BasicModal>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
ref
,
computed
,
unref
}
from
'vue'
;
import
{
BasicModal
,
useModalInner
}
from
'@/components/Modal'
;
import
{
BasicForm
,
useForm
}
from
'@/components/Form'
;
import
{
accountFormSchema
}
from
'./account.data'
;
import
{
getDeptList
}
from
'@/api/demo/system'
;
defineOptions
({
name
:
'AccountModal'
});
const
emit
=
defineEmits
([
'success'
,
'register'
]);
const
isUpdate
=
ref
(
true
);
const
rowId
=
ref
(
''
);
const
[
registerForm
,
{
setFieldsValue
,
updateSchema
,
resetFields
,
validate
}]
=
useForm
({
labelWidth
:
100
,
baseColProps
:
{
span
:
24
},
schemas
:
accountFormSchema
,
showActionButtonGroup
:
false
,
actionColOptions
:
{
span
:
23
,
},
});
const
[
registerModal
,
{
setModalProps
,
closeModal
}]
=
useModalInner
(
async
(
data
)
=>
{
resetFields
();
setModalProps
({
confirmLoading
:
false
});
isUpdate
.
value
=
!!
data
?.
isUpdate
;
if
(
unref
(
isUpdate
))
{
rowId
.
value
=
data
.
record
.
id
;
setFieldsValue
({
...
data
.
record
,
});
}
const
treeData
=
await
getDeptList
();
updateSchema
([
{
field
:
'pwd'
,
show
:
!
unref
(
isUpdate
),
},
{
field
:
'dept'
,
componentProps
:
{
treeData
},
},
]);
});
const
getTitle
=
computed
(()
=>
(
!
unref
(
isUpdate
)
?
'新增账号'
:
'编辑账号'
));
async
function
handleSubmit
()
{
try
{
const
values
=
await
validate
();
setModalProps
({
confirmLoading
:
true
});
// TODO custom api
console
.
log
(
values
);
closeModal
();
emit
(
'success'
,
{
isUpdate
:
unref
(
isUpdate
),
values
:
{
...
values
,
id
:
rowId
.
value
}
});
}
finally
{
setModalProps
({
confirmLoading
:
false
});
}
}
</
script
>
src/views/system/user/DeptTree.vue
0 → 100644
View file @
e622c0a2
<
template
>
<div
class=
"m-4 mr-0 overflow-hidden bg-white"
>
<BasicTree
title=
"部门列表"
toolbar
search
treeWrapperClassName=
"h-[calc(100%-35px)] overflow-auto"
:clickRowToExpand=
"false"
:treeData=
"treeData"
:fieldNames=
"
{ key: 'id', title: 'deptName' }"
@select="handleSelect"
/>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
onMounted
,
ref
}
from
'vue'
;
import
{
BasicTree
,
TreeItem
}
from
'@/components/Tree'
;
import
{
getDeptList
}
from
'@/api/demo/system'
;
defineOptions
({
name
:
'DeptTree'
});
const
emit
=
defineEmits
([
'select'
]);
const
treeData
=
ref
<
TreeItem
[]
>
([]);
async
function
fetch
()
{
treeData
.
value
=
(
await
getDeptList
())
as
unknown
as
TreeItem
[];
}
function
handleSelect
(
keys
)
{
emit
(
'select'
,
keys
[
0
]);
}
onMounted
(()
=>
{
fetch
();
});
</
script
>
src/views/system/user/account.data.ts
0 → 100644
View file @
e622c0a2
import
{
getAllRoleList
,
isAccountExist
}
from
'@/api/demo/system'
;
import
{
BasicColumn
,
FormSchema
}
from
'@/components/Table'
;
/**
* transform mock data
* {
* 0: '华东分部',
* '0-0': '华东分部-研发部'
* '0-1': '华东分部-市场部',
* ...
* }
*/
export
const
deptMap
=
(()
=>
{
const
pDept
=
[
'华东分部'
,
'华南分部'
,
'西北分部'
];
const
cDept
=
[
'研发部'
,
'市场部'
,
'商务部'
,
'财务部'
];
return
pDept
.
reduce
((
map
,
p
,
pIdx
)
=>
{
map
[
pIdx
]
=
p
;
cDept
.
forEach
((
c
,
cIndex
)
=>
(
map
[
`
${
pIdx
}
-
${
cIndex
}
`
]
=
`
${
p
}
-
${
c
}
`
));
return
map
;
},
{});
})();
export
const
columns
:
BasicColumn
[]
=
[
{
title
:
'登录名'
,
dataIndex
:
'username'
,
width
:
120
,
},
{
title
:
'姓名'
,
dataIndex
:
'name'
,
width
:
120
,
},
{
title
:
'手机号'
,
dataIndex
:
'phone'
,
width
:
120
,
},
{
title
:
'状态'
,
dataIndex
:
'flag'
,
width
:
180
,
},
{
title
:
'创建时间'
,
dataIndex
:
'createDate'
,
width
:
200
,
},
// {
// title: '所属部门',
// dataIndex: 'dept',
// customRender: ({ value }) => {
// return deptMap[value];
// },
// },
];
export
const
searchFormSchema
:
FormSchema
[]
=
[
{
field
:
'username'
,
label
:
'登录名'
,
component
:
'Input'
,
colProps
:
{
span
:
8
},
},
{
field
:
'flag'
,
label
:
'状态'
,
component
:
'Select'
,
componentProps
:
{
options
:
[
{
label
:
'启用'
,
value
:
'1'
},
{
label
:
'停用'
,
value
:
'0'
},
],
},
colProps
:
{
span
:
8
},
},
];
export
const
accountFormSchema
:
FormSchema
[]
=
[
{
field
:
'account'
,
label
:
'用户名'
,
component
:
'Input'
,
helpMessage
:
[
'本字段演示异步验证'
,
'不能输入带有admin的用户名'
],
rules
:
[
{
required
:
true
,
message
:
'请输入用户名'
,
},
{
trigger
:
'blur'
,
validator
(
_
,
value
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
value
)
return
resolve
();
isAccountExist
(
value
)
.
then
(
resolve
)
.
catch
((
err
)
=>
{
reject
(
err
.
message
||
'验证失败'
);
});
});
},
},
],
},
{
field
:
'pwd'
,
label
:
'密码'
,
component
:
'InputPassword'
,
required
:
true
,
ifShow
:
false
,
},
{
label
:
'角色'
,
field
:
'role'
,
component
:
'ApiSelect'
,
componentProps
:
{
api
:
getAllRoleList
,
labelField
:
'roleName'
,
valueField
:
'roleValue'
,
},
required
:
true
,
},
{
field
:
'dept'
,
label
:
'所属部门'
,
component
:
'TreeSelect'
,
componentProps
:
{
fieldNames
:
{
label
:
'deptName'
,
value
:
'id'
,
},
getPopupContainer
:
()
=>
document
.
body
,
},
required
:
true
,
},
{
field
:
'nickname'
,
label
:
'昵称'
,
component
:
'Input'
,
required
:
true
,
},
{
label
:
'邮箱'
,
field
:
'email'
,
component
:
'Input'
,
required
:
true
,
},
{
label
:
'备注'
,
field
:
'remark'
,
component
:
'InputTextArea'
,
},
];
src/views/system/user/index.vue
View file @
e622c0a2
<
template
>
<div>
用戶管理
</div>
<PageWrapper
dense
contentFullHeight
fixedHeight
contentClass=
"flex"
>
<!--
<DeptTree
class=
"w-1/4 xl:w-1/5"
@
select=
"handleSelect"
/>
-->
<BasicTable
@
register=
"registerTable"
class=
"w-3/4 xl:w-4/5"
:searchInfo=
"searchInfo"
>
<template
#
toolbar
>
<a-button
type=
"primary"
@
click=
"handleCreate"
>
新增
</a-button>
<a-button
type=
"primary"
@
click=
"handleExport"
>
导出
</a-button>
</
template
>
<
template
#
bodyCell=
"{ column, record }"
>
<template
v-if=
"column.key === 'action'"
>
<TableAction
:actions=
"[
{
icon: 'clarity:info-standard-line',
tooltip: '详情',
onClick: handleView.bind(null, record),
},
{
icon: 'clarity:note-edit-line',
tooltip: '编辑',
onClick: handleEdit.bind(null, record),
},
{
icon: 'ant-design:delete-outlined',
color: 'error',
tooltip: '删除',
popConfirm: {
title: '是否确认删除',
placement: 'left',
confirm: handleDelete.bind(null, record),
},
},
]"
/>
</
template
>
</template>
</BasicTable>
<AccountModal
@
register=
"registerModal"
@
success=
"handleSuccess"
/>
</PageWrapper>
</template>
<
script
lang=
"ts"
setup
>
import
{
reactive
}
from
'vue'
;
</
script
>
import
{
BasicTable
,
useTable
,
TableAction
}
from
'@/components/Table'
;
import
{
getAccountList
}
from
'@/api/demo/system'
;
import
{
PageWrapper
}
from
'@/components/Page'
;
import
DeptTree
from
'./DeptTree.vue'
;
import
{
useModal
}
from
'@/components/Modal'
;
import
AccountModal
from
'./AccountModal.vue'
;
import
{
columns
,
searchFormSchema
}
from
'./account.data'
;
import
{
useGo
}
from
'@/hooks/web/usePage'
;
defineOptions
({
name
:
'AccountManagement'
});
const
go
=
useGo
();
const
[
registerModal
,
{
openModal
}]
=
useModal
();
const
searchInfo
=
reactive
<
Recordable
>
({});
const
[
registerTable
,
{
reload
,
updateTableDataRecord
,
getSearchInfo
}]
=
useTable
({
title
:
'用户管理列表'
,
api
:
getAccountList
,
rowKey
:
'id'
,
columns
,
formConfig
:
{
labelWidth
:
120
,
schemas
:
searchFormSchema
,
autoSubmitOnEnter
:
true
,
},
useSearchForm
:
true
,
showTableSetting
:
false
,
bordered
:
true
,
handleSearchInfoFn
(
info
)
{
console
.
log
(
'handleSearchInfoFn'
,
info
);
return
info
;
},
actionColumn
:
{
width
:
120
,
title
:
'操作'
,
dataIndex
:
'action'
,
// slots: { customRender: 'action' },
},
});
<
style
scoped
>
function
handleCreate
()
{
openModal
(
true
,
{
isUpdate
:
false
,
});
}
</
style
>
function
handleEdit
(
record
:
Recordable
)
{
console
.
log
(
record
);
openModal
(
true
,
{
record
,
isUpdate
:
true
,
});
}
function
handleDelete
(
record
:
Recordable
)
{
console
.
log
(
record
);
}
function
handleExport
()
{
console
.
log
(
getSearchInfo
());
}
function
handleSuccess
({
isUpdate
,
values
})
{
if
(
isUpdate
)
{
// 演示不刷新表格直接更新内部数据。
// 注意:updateTableDataRecord要求表格的rowKey属性为string并且存在于每一行的record的keys中
const
result
=
updateTableDataRecord
(
values
.
id
,
values
);
console
.
log
(
result
);
}
else
{
reload
();
}
}
function
handleSelect
(
deptId
=
''
)
{
searchInfo
.
deptId
=
deptId
;
reload
();
}
function
handleView
(
record
:
Recordable
)
{
go
(
'/system/account_detail/'
+
record
.
id
);
}
</
script
>
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