专家库查询界面

This commit is contained in:
caoqianming 2021-07-09 16:07:28 +08:00
parent 3cd25e051e
commit a9efc7c762
20 changed files with 482 additions and 8 deletions

View File

@ -0,0 +1,29 @@
import request from '@/utils/request'
export function getExpertList(query) {
return request({
url: '/expert/expert/',
method: 'get',
params: query
})
}
export function createExpert(data) {
return request({
url: '/expert/expert/',
method: 'post',
data
})
}
export function updateExpert(id, data) {
return request({
url: `/expert/expert/${id}/`,
method: 'put',
data
})
}
export function deleteExpert(id) {
return request({
url: `/expert/expert/${id}/`,
method: 'delete'
})
}

View File

@ -35,7 +35,7 @@ export default {
pageSizes: { pageSizes: {
type: Array, type: Array,
default() { default() {
return [10, 20, 30, 50] return [12, 24, 36, 48]
} }
}, },
layout: { layout: {

View File

@ -52,7 +52,8 @@ export default {
computed: { computed: {
...mapGetters([ ...mapGetters([
'sidebar', 'sidebar',
'avatar' 'avatar',
'name'
]) ])
}, },
methods: { methods: {

View File

@ -24,7 +24,7 @@ export default {
}, },
data() { data() {
return { return {
title: 'Django Vue Admin', title: '总院专家库',
logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png' logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png'
} }
} }

View File

@ -78,6 +78,17 @@ export const constantRoutes = [
* the routes that need to be dynamically loaded based on user perms * the routes that need to be dynamically loaded based on user perms
*/ */
export const asyncRoutes = [ export const asyncRoutes = [
{
path: '/search',
component: Layout,
redirect: '/search',
children: [{
path: 'search',
name: 'Search',
component: () => import('@/views/search/index'),
meta: { title: '专家检索', icon: 'search' }
}]
},
{ {
path: '/system', path: '/system',
component: Layout, component: Layout,

View File

@ -1,6 +1,6 @@
module.exports = { module.exports = {
title: '管理系统', title: '总院专家库',
/** /**
* @type {boolean} true | false * @type {boolean} true | false

View File

@ -10,6 +10,7 @@ body {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
background-color: #f0f2f5;
} }
label { label {

View File

@ -1,6 +1,6 @@
import defaultSettings from '@/settings' import defaultSettings from '@/settings'
const title = defaultSettings.title || '认证系统' const title = defaultSettings.title || '总院专家库'
export default function getPageTitle(pageTitle) { export default function getPageTitle(pageTitle) {
if (pageTitle) { if (pageTitle) {

View File

@ -3,7 +3,7 @@
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
<div class="title-container"> <div class="title-container">
<h3 class="title">系统登陆</h3> <h3 class="title">总院专家库</h3>
</div> </div>
<el-form-item prop="username"> <el-form-item prop="username">

View File

@ -0,0 +1,294 @@
<template>
<div class="app-container">
<el-card>
<div slot="header" class="clearfix">
<span>专家库检索</span>
</div>
<el-row type="flex">
<el-col :sm="18">
<el-row :gutter="8">
<el-col :xs="16" :sm="20">
<el-input
v-model="listQuery.search"
placeholder="请输入关键字"
@keyup.enter.native="handleFilter"
></el-input>
</el-col>
<el-col :xs="8" :sm="4">
<el-button
type="primary"
style="width: 100%"
@click="handleFilter"
>搜索一下</el-button
>
</el-col>
</el-row>
</el-col>
</el-row>
<el-row style="margin-top:6px">
<el-col :xs="12" :sm="12" :lg="6" :xl="6">
<el-select
v-model="listQuery.hdegree"
placeholder="最高学历"
clearable
@change="handleFilter"
style="width:100%"
>
<el-option
v-for="item in degreeOptions"
:key="item.key"
:label="item.label"
:value="item.key"
/>
</el-select>
</el-col>
</el-row>
</el-card>
<el-card style="margin-top: 6px">
<div slot="header" class="clearfix">
<span>专家库</span>
</div>
<p
style="text-align: center; font-weight: bold; color: gray"
v-if="tableData.count == 0"
>
暂无数据
</p>
<el-row :gutter="10" v-else v-loading="listLoading">
<el-col
:xs="12"
:sm="6"
:lg="6"
:xl="4"
v-for="item in tableData.results"
v-bind:key="item.id"
>
<el-card>
<div slot="header" class="clearfix">
<span>{{ item.name }}</span>
<el-button style="float: right; padding: 3px 0" type="text"
>更多信息</el-button
>
</div>
<div>
<el-row :gutter="8">
<el-col :xs="9" :sm="10" :lg="8" :xl="8">
<el-image
style="width: 100%"
:src="item.photo"
:preview-src-list="[item.photo]"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
</el-col>
<el-col :xs="15" :sm="14" :lg="16" :xl="16">
<div style="text-align: center">
<div
style="
font-weight: bold;
font-size: 18px;
margin-top: 4px;
"
>
<i
class="el-icon-male"
style="color: blue; font-weight: bold"
v-if="item.gender == ''"
></i>
<i
class="el-icon-female"
style="color: blue; font-weight: red"
v-else
></i>
{{ item.name }}
</div>
<div style="margin-top: 4px">{{ item.hdegree }}</div>
<div style="margin-top: 4px">{{ item.idnumber }}</div>
</div>
</el-col>
</el-row>
<el-row :gutter="2" style="font-size: 14px" v-if="item.project_.length">
<el-col
:xs="24"
:sm="24"
:lg="6"
:xl="4"
style="color: gray; font-weight: bold; margin-top: 2px"
>项目经历</el-col
>
<el-col
:xs="24"
:sm="24"
:lg="18"
:xl="20"
style="margin-top: 2px"
>
<div v-for="x in item.project_" v-bind:key="x.id" v-html="x.name_">
</div>
</el-col>
</el-row>
<el-row :gutter="2" style="font-size: 14px" v-if="item.paper_.length">
<el-col
:xs="24"
:sm="24"
:lg="6"
:xl="4"
style="color: gray; font-weight: bold; margin-top: 2px"
v-if="item.paper_.length"
>论文/著作</el-col
>
<el-col
:xs="24"
:sm="24"
:lg="18"
:xl="20"
style="margin-top: 2px"
>
<div v-for="x in item.paper_" v-bind:key="x.id" class="tip" v-html="x.name_">
</div>
</el-col>
</el-row>
<el-row :gutter="2" style="font-size: 14px" v-if="item.award_.length">
<el-col
:xs="24"
:sm="24"
:lg="6"
:xl="4"
style="color: gray; font-weight: bold; margin-top: 2px"
v-if="item.award_.length"
>所获奖项</el-col
>
<el-col
:xs="24"
:sm="24"
:lg="18"
:xl="20"
style="margin-top: 2px"
>
<div v-for="x in item.award_" v-bind:key="x.id" class="tip" v-html="x.name_">
</div>
</el-col>
</el-row>
</div>
</el-card>
</el-col>
</el-row>
<pagination
style="margin-top: 6px"
v-show="tableData.count > 0"
:total="tableData.count"
:page.sync="listQuery.page"
:limit.sync="listQuery.page_size"
@pagination="getList"
/>
</el-card>
</div>
</template>
<script>
import { getExpertList } from "@/api/expert";
import checkPermission from "@/utils/permission";
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
export default {
components: { Pagination },
data() {
return {
search: null,
listQuery: {
page: 1,
page_size: 12,
search: "",
},
listLoading: false,
tableData: {
count: 0,
results: [],
},
degreeOptions:[
{ key: "博士研究生", value: "博士研究生" },
{ key: "硕士研究生", value: "硕士研究生" },
{ key: "本科", value: "本科" },
{ key: "大专", value: "大专" },
]
};
},
created() {
this.getList();
},
methods: {
checkPermission,
getList() {
this.listLoading = true;
getExpertList(this.listQuery)
.then((res) => {
this.listLoading = false;
this.tableData = res.data;
//高亮显示
this.showLight();
})
.catch((e) => {
this.listLoading = false;
});
},
handleFilter() {
this.page = 1;
this.getList();
},
lessStr(data, arg) {
for (var i = 0; i < data.length; i++) {
let len1 = data[i][arg].length;
if (len1 > 2) {
data[i][arg] = data[i][arg].slice(0, 2);
}
for (var x = 0; x < data[i][arg].length; x++) {
data[i][arg][x].name_ = data[i][arg][x].name.substr(0, 14) + "...";
}
}
},
lessStr2(data, arg, searchList) {
for (var i = 0; i < data.length; i++) {
//项目经历
var ll = [];
for (var x = 0; x < data[i][arg].length; x++) {
for (var m = 0; m < searchList.length; m++) {
if (data[i][arg][x].name.indexOf(searchList[m]) != -1) {
let sm = data[i][arg][x]
sm.name_ = data[i][arg][x].name.replace(
searchList[m],
'<span style="color:red;">' + searchList[m] + "</span>"
);
ll.push(sm);
}
}
}
data[i][arg]=ll
}
},
showLight() {
var data = this.tableData.results
if (this.listQuery.search == "") {
//项目经历
this.lessStr(data, "project_");
//论文
this.lessStr(data, "paper_");
//获奖
this.lessStr(data, "award_");
} else {
let searchList = this.listQuery.search.split(" ");
this.lessStr2(data, 'project_', searchList)
this.lessStr2(data, 'paper_', searchList)
this.lessStr2(data, 'award_', searchList)
}
},
},
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,21 @@
# Generated by Django 3.1.8 on 2021-07-08 02:43
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('expert', '0003_historicalexpert'),
]
operations = [
migrations.AlterModelOptions(
name='expert',
options={'verbose_name': '专家信息', 'verbose_name_plural': '专家信息'},
),
migrations.AlterModelOptions(
name='historicalexpert',
options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical 专家信息'},
),
]

View File

@ -0,0 +1,16 @@
# Generated by Django 3.1.8 on 2021-07-08 02:44
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('expert', '0004_auto_20210708_1043'),
]
operations = [
migrations.DeleteModel(
name='HistoricalExpert',
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.1.8 on 2021-07-08 08:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('expert', '0005_delete_historicalexpert'),
]
operations = [
migrations.AddField(
model_name='expert',
name='Hdegree',
field=models.CharField(choices=[('', ''), ('', '')], default='本科', max_length=10, verbose_name='最高学历'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.1.8 on 2021-07-08 08:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('expert', '0006_expert_hdegree'),
]
operations = [
migrations.RenameField(
model_name='expert',
old_name='Hdegree',
new_name='hdegree',
),
]

View File

@ -10,6 +10,12 @@ class Expert(CommonBModel):
('', ''), ('', ''),
('', ''), ('', ''),
) )
degree_choices = (
('大专', '大专'),
('本科', '本科'),
('硕士研究生', '硕士研究生'),
('博士研究生', '博士研究生'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, verbose_name="关联账户", related_name="expert_user") user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, verbose_name="关联账户", related_name="expert_user")
name = models.CharField(verbose_name="姓名", max_length=100) name = models.CharField(verbose_name="姓名", max_length=100)
@ -17,7 +23,7 @@ class Expert(CommonBModel):
idnumber = models.CharField(verbose_name="身份证号", max_length=40) idnumber = models.CharField(verbose_name="身份证号", max_length=40)
paddress = models.TextField(verbose_name="通讯地址") paddress = models.TextField(verbose_name="通讯地址")
photo = models.CharField(verbose_name="证件照", max_length=100, null=True, blank=True) photo = models.CharField(verbose_name="证件照", max_length=100, null=True, blank=True)
history = HistoricalRecords() hdegree = models.CharField(verbose_name="最高学历",choices=gender_choices, default='本科', max_length=10)
class Meta: class Meta:
verbose_name = '专家信息' verbose_name = '专家信息'

View File

@ -0,0 +1,37 @@
from rest_framework.serializers import ModelSerializer
from .models import Award, Expert, Paper, Project, WorkExperience
class WorkExperienceSimpleSerializer(ModelSerializer):
class Meta:
model = WorkExperience
fields = ['id', 'name']
class ProjectSimpleSerializer(ModelSerializer):
class Meta:
model = Project
fields = ['id', 'name']
class PaperSimpleSerializer(ModelSerializer):
class Meta:
model = Paper
fields = ['id', 'name']
class AwardSimpleSerializer(ModelSerializer):
class Meta:
model = Award
fields = ['id', 'name']
class ExpertListSerializer(ModelSerializer):
workexperience_ = WorkExperienceSimpleSerializer(source='workexperience_expert', many=True, read_only=True)
project_ = ProjectSimpleSerializer(source='project_expert', many=True, read_only=True)
paper_ = PaperSimpleSerializer(source='paper_expert', many=True, read_only=True)
award_ = AwardSimpleSerializer(source='award_expert', many=True, read_only=True)
class Meta:
model = Expert
fields = '__all__'
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('workexperience_expert','project_expert', 'paper_expert', 'award_expert')
return queryset

View File

@ -0,0 +1,10 @@
from django.urls import path, include
from .views import ExpertViewSet
from rest_framework import routers
router = routers.DefaultRouter()
router.register('expert', ExpertViewSet, basename="expert")
urlpatterns = [
path('', include(router.urls)),
]

View File

@ -1,3 +1,14 @@
from django.shortcuts import render from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from .models import Expert
from .serializers import ExpertListSerializer
from apps.system.mixins import OptimizationMixin
# Create your views here. # Create your views here.
class ExpertViewSet(OptimizationMixin, ModelViewSet):
perms_map={'get':'expert_view'}
queryset = Expert.objects.all()
search_fields = ['name', 'workexperience_expert__name', 'project_expert__name', 'paper_expert__name', 'award_expert__name']
filterset_fields = ['hdegree']
serializer_class = ExpertListSerializer
ordering = ['-create_time']

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -49,6 +49,7 @@ urlpatterns = [
path('token/black/', LogoutView.as_view(), name='token_black'), path('token/black/', LogoutView.as_view(), name='token_black'),
path('system/', include('apps.system.urls')), path('system/', include('apps.system.urls')),
path('monitor/', include('apps.monitor.urls')), path('monitor/', include('apps.monitor.urls')),
path('expert/', include('apps.expert.urls')),
# api文档 # api文档
path('docs/', include_docs_urls(title="接口文档", authentication_classes=[], permission_classes=[])), path('docs/', include_docs_urls(title="接口文档", authentication_classes=[], permission_classes=[])),