user-detail

This commit is contained in:
xiaomlove
2021-04-27 19:13:32 +08:00
parent d1b7561aae
commit d2e05c812e
20 changed files with 594 additions and 50 deletions
+1 -1
View File
@@ -3,5 +3,5 @@ import App from './App.vue'
import ElementPlus from 'element-plus'
import router from './router/index'
import 'element-plus/lib/theme-chalk/index.css'
// import './styles/common.scss'
import './styles/common.scss'
createApp(App).use(ElementPlus).use(router).mount('#app')
+5
View File
@@ -23,6 +23,11 @@ const router = createRouter({
name: 'user-form',
component: () => import('../views/user/form.vue')
},
{
path: '/user-detail',
name: 'user-detail',
component: () => import('../views/user/detail.vue')
},
{
path: '/exam',
name: 'exam',
+4
View File
@@ -0,0 +1,4 @@
.nexus-table-header {
display: flex;
justify-content: space-between;
}
+8 -2
View File
@@ -26,6 +26,9 @@ const api = {
listUser: (params = {}) => {
return axios.get('user', {params: params});
},
getUser: (id, params = {}) => {
return axios.get('user/' + id, {params: params});
},
getUserBase: (params = {}) => {
return axios.get('user-base', {params: params});
},
@@ -37,7 +40,7 @@ const api = {
return axios.get('exam', {params: params});
},
listExamIndex: (params = {}) => {
return axios.get('exam-index', {params: params});
return axios.get('exam-indexes', {params: params});
},
storeExam: (params = {}) => {
return axios.post('exam', params);
@@ -52,11 +55,14 @@ const api = {
return axios.delete('exam/' + id);
},
listClass: (params = {}) => {
return axios.get('class', {params: params});
return axios.get('user-classes', {params: params});
},
listExamUser: (params = {}) => {
return axios.get('exam-users', {params: params});
},
deleteExamUser: (id) => {
return axios.delete('exam-users/' + id);
},
}
export default api
+1
View File
@@ -42,6 +42,7 @@ export const pathMap = {
'agent-allow-form': 'Agent allow form',
'user': 'User',
'user-form': 'User form',
'user-detail': 'User detail',
'exam': 'Exam',
'exam-form': 'Exam form',
'exam-user': 'Exam user',
+7 -2
View File
@@ -1,8 +1,13 @@
<template>
<el-card class="">
<template #header>
<div class="header">
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">Add</el-button>
<div class="nexus-table-header">
<div class="left">
</div>
<div class="right">
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">Add</el-button>
</div>
</div>
</template>
<el-table
+18 -11
View File
@@ -57,17 +57,17 @@
label="Action"
width="100"
>
<!-- <template #default="scope">-->
<!-- <a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.id)">Edit</a>-->
<!-- <el-popconfirm-->
<!-- title="Confirm Delete ?"-->
<!-- @confirm="handleDelete(scope.row.id)"-->
<!-- >-->
<!-- <template #reference>-->
<!-- <a style="cursor: pointer">Delete</a>-->
<!-- </template>-->
<!-- </el-popconfirm>-->
<!-- </template>-->
<template #default="scope">
<a style="cursor: pointer; margin-right: 10px" @click="handleDetail(scope.row.uid)">Detail</a>
<!-- <el-popconfirm-->
<!-- title="Confirm Delete ?"-->
<!-- @confirm="handleDelete(scope.row.id)"-->
<!-- >-->
<!-- <template #reference>-->
<!-- <a style="cursor: pointer">Delete</a>-->
<!-- </template>-->
<!-- </el-popconfirm>-->
</template>
</el-table-column>
</el-table>
<!--总数超过一页再展示分页器-->
@@ -130,6 +130,12 @@ export default {
resetTableSort(val, state)
fetchTableData()
}
const handleDetail = (id) => {
router.push({
name: 'user-detail',
query: {id: id}
})
}
const formatColumnUser = (row, column) => {
return row.user.username
@@ -148,6 +154,7 @@ export default {
handleAdd,
handleEdit,
handleDelete,
handleDetail,
fetchTableData,
changePage,
handleSortChange,
+182
View File
@@ -0,0 +1,182 @@
<template>
<div class="page-user-detail" v-loading="loading">
<el-card>
<template #header>
<div class="card-header">
<span>Base Info</span>
</div>
</template>
<table class="table-base-info">
<tr>
<th>Field</th>
<th>Value</th>
<th>Actions</th>
<th>Other</th>
</tr>
<tr>
<td>Username</td>
<td>{{baseInfo.username}}</td>
<td></td>
<td colspan="7">
<div class="other-actions">
<el-button type="primary" size="mini">Reset password</el-button>
<el-button type="primary" size="mini">PM</el-button>
<el-button type="primary" size="mini" @click="handleAssignExam">Assign exam</el-button>
</div>
</td>
</tr>
<tr>
<td>Email</td>
<td>{{baseInfo.email}}</td>
<td><el-button size="mini">Change</el-button></td>
</tr>
<tr>
<td>Added</td>
<td>{{baseInfo.added}}</td>
</tr>
<tr>
<td>Class</td>
<td>{{baseInfo.class_text}}</td>
</tr>
<tr>
<td>Uploaded</td>
<td>{{baseInfo.uploaded}}</td>
<td><el-button size="mini">Add</el-button></td>
</tr>
<tr>
<td>Downloaded</td>
<td>{{baseInfo.downloaded}}</td>
<td><el-button size="mini">Add</el-button></td>
</tr>
<tr>
<td>Bonus</td>
<td>{{baseInfo.bonus}}</td>
<td><el-button size="mini">Add</el-button></td>
</tr>
</table>
</el-card>
<el-card v-if="examInfo">
<template #header>
<div class="card-header">
<span>Exam</span>
</div>
</template>
<el-row>
<el-col :span="12">
<table class="table-base-info">
<tr>
<td>Name</td>
<td>{{examInfo.exam && examInfo.exam.name}}</td>
</tr>
<tr>
<td>Created At</td>
<td>{{examInfo.created_at}}</td>
</tr>
<tr>
<td>Exam Time</td>
<td>{{examInfo.begin}} ~ {{examInfo.end}}</td>
</tr>
<tr>
<td>Status</td>
<td>{{examInfo.status_text}}</td>
</tr>
<tr>
<td>Action</td>
<td>
<el-popconfirm
title="Confirm Remove ?"
@confirm="handleRemoveExam(examInfo.id)"
>
<template #reference>
<el-button type="danger" size="small">Remove</el-button>
</template>
</el-popconfirm>
</td>
</tr>
</table>
</el-col>
<el-col :span="12">
<el-table :data="examInfo.progress_formatted">
<el-table-column prop="name" label="Index"></el-table-column>
<el-table-column prop="require_value_formatted" label="Require"></el-table-column>
<el-table-column prop="current_value_formatted" label="Current"></el-table-column>
<el-table-column prop="result" label="Result">
<template #default="scope">
<el-tag v-if="scope.row.passed" type="success">Pass !</el-tag>
<el-tag v-if="!scope.row.passed" type="danger">Not Pass !</el-tag>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</el-card>
</div>
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue'
import { ElMessage } from 'element-plus'
import {useRoute, useRouter} from 'vue-router'
import api from '../../utils/api'
export default {
name: "UserDetail",
setup() {
const route = useRoute()
const router = useRouter()
const { id } = route.query
const state = reactive({
loading: false,
baseInfo: {},
examInfo: {},
matchExams: [],
dialogAssignExamFormVisible: false,
assignExamFormData: {
exam_id: '',
timeRange: []
}
})
onMounted(() => {
fetchPageData()
})
const fetchPageData = async () => {
state.loading = true;
let res = await api.getUser(id)
state.loading = false
state.baseInfo = res.data.base_info
state.examInfo = res.data.exam_info
}
const handleRemoveExam = async (id) => {
let res = await api.deleteExamUser(id)
ElMessage.success(res.msg)
await fetchPageData()
}
const handleAssignExam = async () => {
state.dialogAssignExamFormVisible = true;
}
return {
...toRefs(state),
handleRemoveExam,
handleAssignExam
}
}
}
</script>
<style lang="scss" scoped>
.el-card {
margin-bottom: 20px;
}
.table-base-info {
width: 100%;
text-align: left;
tr {
th {
padding-bottom: 10px;
}
td {
padding: 10px 0;
}
}
}
</style>
@@ -0,0 +1,38 @@
<template>
<el-dialog
title="Assign exam to user"
v-model="dialogAssignExamFormVisible"
center
class="dialog-assign-exam"
>
<el-form :model="assignExamFormData" label-width="150px">
<el-form-item label="Exam">
<el-select v-model="assignExamFormData.exam_id" placeholder="Select an exam...">
<el-option
v-for="item in matchExams"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="Exam time range">
<el-date-picker
v-model="assignExamFormData.timeRange"
type="datetimerange"
format="YYYY-MM-DD HH:mm:ss"
range-separator="to"
start-placeholder="Begin"
end-placeholder="End">
</el-date-picker>
<div class="time-range-help-text">If the time range is not specified, the exam's own configured time range will be used.</div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogAssignExamFormVisible = false"> </el-button>
<el-button type="primary" @click="dialogAssignExamFormVisible = false"> </el-button>
</span>
</template>
</el-dialog>
</template>
+11 -3
View File
@@ -77,8 +77,8 @@
label="Action"
width="100"
>
<!-- <template #default="scope">-->
<!-- <a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.id)">Edit</a>-->
<template #default="scope">
<a style="cursor: pointer; margin-right: 10px" @click="handleDetail(scope.row.id)">Detail</a>
<!-- <el-popconfirm-->
<!-- title="Confirm Delete ?"-->
<!-- @confirm="handleDelete(scope.row.id)"-->
@@ -87,7 +87,7 @@
<!-- <a style="cursor: pointer">Delete</a>-->
<!-- </template>-->
<!-- </el-popconfirm>-->
<!-- </template>-->
</template>
</el-table-column>
</el-table>
<!--总数超过一页再展示分页器-->
@@ -151,6 +151,13 @@ export default {
fetchTableData()
}
const handleDetail = (id) => {
router.push({
name: 'user-detail',
query: {id: id}
})
}
const formatColumnClass = (row, column) => {
return row.class_text
}
@@ -168,6 +175,7 @@ export default {
handleAdd,
handleEdit,
handleDelete,
handleDetail,
fetchTableData,
changePage,
handleSortChange,