增加省管理员和本单位管理员

This commit is contained in:
caoqianming 2021-04-05 21:31:53 +08:00
parent 0827bd6f95
commit 45265db72a
23 changed files with 315 additions and 152 deletions

View File

@ -3451,8 +3451,8 @@
}, },
"china-area-data": { "china-area-data": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/china-area-data/-/china-area-data-5.0.1.tgz", "resolved": "https://registry.npm.taobao.org/china-area-data/download/china-area-data-5.0.1.tgz",
"integrity": "sha512-BQDPpiv5Nn+018ekcJK2oSD9PAD+E1bvXB0wgabc//dFVS/KvRqCgg0QOEUt3vBkx9XzB5a9BmkJCEZDBxVjVw==" "integrity": "sha1-eUO4OgYZ8DO7WJPagMtG5S5EvmY="
}, },
"chokidar": { "chokidar": {
"version": "2.1.8", "version": "2.1.8",
@ -5035,8 +5035,8 @@
}, },
"element-china-area-data": { "element-china-area-data": {
"version": "5.0.2", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/element-china-area-data/-/element-china-area-data-5.0.2.tgz", "resolved": "https://registry.npm.taobao.org/element-china-area-data/download/element-china-area-data-5.0.2.tgz",
"integrity": "sha512-vLQuvOKJy/uiX7MRHEk3x/j09hipuIl6DJ/C4XFUG7D7Pj3O47sy+Y6aAArM6k9v8cD9UX6e+yz2S4J+IPnZ8g==", "integrity": "sha1-AGwmWUuIZcthmZQGPHMlYuRYPTA=",
"requires": { "requires": {
"china-area-data": "^5.0.1", "china-area-data": "^5.0.1",
"lodash-es": "^4.17.15" "lodash-es": "^4.17.15"
@ -9900,8 +9900,8 @@
}, },
"lodash-es": { "lodash-es": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "resolved": "https://registry.npm.taobao.org/lodash-es/download/lodash-es-4.17.21.tgz?cache=0&sync_timestamp=1613836280924&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash-es%2Fdownload%2Flodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" "integrity": "sha1-Q+YmxG5lkbd1C+srUBFzkMYJ4+4="
}, },
"lodash.defaultsdeep": { "lodash.defaultsdeep": {
"version": "4.6.1", "version": "4.6.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

View File

@ -5,6 +5,9 @@
<breadcrumb class="breadcrumb-container" /> <breadcrumb class="breadcrumb-container" />
<div class="right-menu"> <div class="right-menu">
<div class="right-menu-item" >
{{name}}
</div>
<el-dropdown class="avatar-container" trigger="click"> <el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar"> <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
@ -49,7 +52,8 @@ export default {
computed: { computed: {
...mapGetters([ ...mapGetters([
'sidebar', 'sidebar',
'avatar' 'avatar',
'name'
]) ])
}, },
methods: { methods: {

View File

@ -2,11 +2,11 @@
<div class="sidebar-logo-container" :class="{'collapse':collapse}"> <div class="sidebar-logo-container" :class="{'collapse':collapse}">
<transition name="sidebarLogoFade"> <transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo"> <!-- <img v-if="logo" :src="logo" class="sidebar-logo"> -->
<h1 v-else class="sidebar-title">{{ title }} </h1> <h1 class="sidebar-title">{{ title }} </h1>
</router-link> </router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/"> <router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo"> <!-- <img v-if="logo" :src="logo" class="sidebar-logo"> -->
<h1 class="sidebar-title">{{ title }} </h1> <h1 class="sidebar-title">{{ title }} </h1>
</router-link> </router-link>
</transition> </transition>

View File

@ -120,7 +120,7 @@ export const asyncRoutes = [
path: 'claim', path: 'claim',
name: 'Claim', name: 'Claim',
component: () => import('@/views/crm/claim.vue'), component: () => import('@/views/crm/claim.vue'),
meta: { title: '认领学员', icon: '', perms: ['consumer_view'] } meta: { title: '认领学员', icon: '', perms: ['consumer_claim'] }
}, },
{ {
path: 'candidate', path: 'candidate',

View File

@ -6,11 +6,11 @@ module.exports = {
* @type {boolean} true | false * @type {boolean} true | false
* @description Whether fix the header * @description Whether fix the header
*/ */
fixedHeader: false, fixedHeader: true,
/** /**
* @type {boolean} true | false * @type {boolean} true | false
* @description Whether show the logo in sidebar * @description Whether show the logo in sidebar
*/ */
sidebarLogo: false sidebarLogo: true
} }

View File

@ -69,7 +69,7 @@
type="primary" type="primary"
size="small" size="small"
@click="handleClaim(scope)" @click="handleClaim(scope)"
:disabled="!checkPermission(['consumer_claim'])" v-if="checkPermission(['consumer_claim'])"
>认领</el-button> >认领</el-button>
</el-button-group> </el-button-group>
</template> </template>

View File

@ -62,7 +62,7 @@
<span>{{ scope.row.create_time }}</span> <span>{{ scope.row.create_time }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="所属"> <el-table-column label="创建管理员">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.create_admin_name }}</span> <span>{{ scope.row.create_admin_name }}</span>
</template> </template>
@ -75,14 +75,14 @@
size="small" size="small"
@click="handleEdit(scope)" @click="handleEdit(scope)"
icon="el-icon-edit" icon="el-icon-edit"
:disabled="!checkPermission(['company_update'])" v-if="checkPermission(['company_update'])"
></el-button> ></el-button>
<el-button <el-button
type="danger" type="danger"
size="small" size="small"
@click="handleDelete(scope)" @click="handleDelete(scope)"
icon="el-icon-delete" icon="el-icon-delete"
:disabled="!checkPermission(['company_delete'])" v-if="checkPermission(['company_delete'])"
></el-button> ></el-button>
<el-button <el-button
v-if="checkPermission(['company_transfer'])" v-if="checkPermission(['company_transfer'])"

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-card> <el-card v-if="checkPermission(['company_view'])">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span>单位</span> <span>单位</span>
</div> </div>
@ -122,7 +122,7 @@
type="primary" type="primary"
icon="el-icon-refresh-left" icon="el-icon-refresh-left"
@click="resetFilter" @click="resetFilter"
>刷新</el-button> >重置</el-button>
</div> </div>
<div style="margin-top:10px"> <div style="margin-top:10px">
@ -239,23 +239,20 @@
size="small" size="small"
@click="handleEdit(scope)" @click="handleEdit(scope)"
icon="el-icon-edit" icon="el-icon-edit"
:disabled="!checkPermission(['consumer_update'])" v-if="checkPermission(['consumer_update'])"
v-if="!scope.row.is_superconsumer"
></el-button> ></el-button>
<el-button <el-button
type="danger" type="danger"
size="small" size="small"
@click="handleDelete(scope)" @click="handleDelete(scope)"
icon="el-icon-delete" icon="el-icon-delete"
:disabled="!checkPermission(['consumer_delete'])" v-if="checkPermission(['consumer_delete'])"
v-if="!scope.row.is_superconsumer"
></el-button> ></el-button>
<el-button <el-button
type="primary" type="primary"
size="small" size="small"
@click="handleUnbind(scope)" @click="handleUnbind(scope)"
:disabled="!checkPermission(['consumer_unbind'])" v-if="scope.row.username&&scope.row.openid&&checkPermission(['consumer_unbind'])"
v-if="scope.row.username&&scope.row.openid"
>解微</el-button> >解微</el-button>
</el-button-group> </el-button-group>
</template> </template>
@ -299,25 +296,6 @@
<el-input placeholder="单位" v-model="consumer.company_.name" readonly> <el-input placeholder="单位" v-model="consumer.company_.name" readonly>
<el-button slot="append" icon="el-icon-search" @click="choose()"></el-button> <el-button slot="append" icon="el-icon-search" @click="choose()"></el-button>
</el-input> </el-input>
<!-- <el-select
v-model="consumer.company"
placeholder="单位"
style="width:100%"
clearable
filterable
remote
:loading="treeLoding"
:remote-method="searchCompany"
loading-text
no-match-text
>
<el-option
v-for="item in companyData"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>-->
</el-form-item> </el-form-item>
<el-form-item label="缴费学科" prop="subjects"> <el-form-item label="缴费学科" prop="subjects">
<el-select v-model="consumer.subjects" placeholder="缴费学科" style="width:100%" multiple> <el-select v-model="consumer.subjects" placeholder="缴费学科" style="width:100%" multiple>

View File

@ -1,11 +1,19 @@
<template> <template>
<div class="login-container"> <div class="login-container">
<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 style="text-align:center;margin-bottom:8px">
<!-- <img class="logo" src="../../assets/logo.png" /> -->
</div>
<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">
<span class="svg-container"> <span class="svg-container">
<svg-icon icon-class="user" /> <svg-icon icon-class="user" />
@ -37,17 +45,24 @@
@keyup.enter.native="handleLogin" @keyup.enter.native="handleLogin"
/> />
<span class="show-pwd" @click="showPwd"> <span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /> <svg-icon
:icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
/>
</span> </span>
</el-form-item> </el-form-item>
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登陆</el-button> <el-button
:loading="loading"
type="primary"
style="width: 100%; margin-bottom: 30px"
@click.native.prevent="handleLogin"
>登陆</el-button
>
<!-- <div class="tips"> <!-- <div class="tips">
<span style="margin-right:20px;">username: admin</span> <span style="margin-right:20px;">username: admin</span>
<span> password: any</span> <span> password: any</span>
</div> --> </div> -->
</el-form> </el-form>
</div> </div>
</template> </template>
@ -56,7 +71,7 @@
// import { validUsername } from '@/utils/validate' // import { validUsername } from '@/utils/validate'
export default { export default {
name: 'Login', name: "Login",
data() { data() {
// const validateUsername = (rule, value, callback) => { // const validateUsername = (rule, value, callback) => {
// if (!validUsername(value)) { // if (!validUsername(value)) {
@ -67,78 +82,82 @@ export default {
// } // }
const validatePassword = (rule, value, callback) => { const validatePassword = (rule, value, callback) => {
if (value.length < 4) { if (value.length < 4) {
callback(new Error('密码长度小于4位!')) callback(new Error("密码长度小于4位!"));
} else { } else {
callback() callback();
} }
} };
return { return {
loginForm: { loginForm: {
username: '', username: "",
password: '' password: "",
}, },
loginRules: { loginRules: {
username: [{ required: true, trigger: 'blur', message: "请输入账户" }], username: [{ required: true, trigger: "blur", message: "请输入账户" }],
password: [{ required: true, trigger: 'blur', validator: validatePassword, message: "请输入密码" }] password: [
{
required: true,
trigger: "blur",
validator: validatePassword,
message: "请输入密码",
},
],
}, },
loading: false, loading: false,
passwordType: 'password', passwordType: "password",
redirect: undefined redirect: undefined,
} };
}, },
watch: { watch: {
$route: { $route: {
handler: function(route) { handler: function (route) {
this.redirect = route.query && route.query.redirect this.redirect = route.query && route.query.redirect;
}, },
immediate: true immediate: true,
} },
}, },
methods: { methods: {
showPwd() { showPwd() {
if (this.passwordType === 'password') { if (this.passwordType === "password") {
this.passwordType = '' this.passwordType = "";
} else { } else {
this.passwordType = 'password' this.passwordType = "password";
} }
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.password.focus() this.$refs.password.focus();
}) });
}, },
handleLogin() { handleLogin() {
this.$refs.loginForm.validate(valid => { this.$refs.loginForm.validate((valid) => {
if (valid) { if (valid) {
this.loading = true this.loading = true;
this.$store.dispatch('user/login', this.loginForm).then(() => { this.$store
this.$router.push({ path: this.redirect || '/crm/consumer' }) .dispatch("user/login", this.loginForm)
this.loading = false .then(() => {
}).catch(() => { this.$router.push({ path: this.redirect || "/crm/consumer" });
this.loading = false this.loading = false;
}) })
.catch(() => {
this.loading = false;
});
} else { } else {
console.log('error submit!!') console.log("error submit!!");
return false return false;
} }
}) });
} },
} },
} };
</script> </script>
<style lang="scss"> <style lang="scss">
/* 修复input 背景不协调 和光标变色 */ /* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */ /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg:#283443; $bg: #283443;
$light_gray:#fff; $light_gray: #fff;
$cursor: #fff; $cursor: #fff;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
/* reset element-ui css */ /* reset element-ui css */
.login-container { .login-container {
.el-input { .el-input {
@ -152,20 +171,18 @@ $cursor: #fff;
-webkit-appearance: none; -webkit-appearance: none;
border-radius: 0px; border-radius: 0px;
padding: 12px 5px 12px 15px; padding: 12px 5px 12px 15px;
color: $light_gray; // color: $light_gray;
height: 47px; height: 47px;
caret-color: $cursor; // caret-color: $cursor;
&:-webkit-autofill { // &:-webkit-autofill {
box-shadow: 0 0 0px 1000px $bg inset !important; // box-shadow: 0 0 0px 1000px inset !important;
-webkit-text-fill-color: $cursor !important; // }
}
} }
} }
.el-form-item { .el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid;
background: rgba(0, 0, 0, 0.1);
border-radius: 5px; border-radius: 5px;
color: #454545; color: #454545;
} }
@ -173,23 +190,26 @@ $cursor: #fff;
</style> </style>
<style lang="scss" scoped> <style lang="scss" scoped>
$bg:#2d3a4b; $bg: #2d3a4b;
$dark_gray:#889aa4; $dark_gray: #889aa4;
$light_gray:#eee; $light_gray: #eee;
.login-container { .login-container {
min-height: 100%; display: flex;
width: 100%; justify-content: center;
background-color: $bg; align-items: center;
overflow: hidden; height: 100%;
background-image: url("../../assets/background.jpg");
background-size: cover;
.login-form { .login-form {
position: relative; border-radius: 6px;
width: 520px; background: #ffffff;
max-width: 100%; padding: 25px 25px 5px 25px;
padding: 160px 35px 0; width: 400px;
margin: 0 auto; .logo {
overflow: hidden; width: 350px;
height: 140px;
}
} }
.tips { .tips {
@ -206,7 +226,7 @@ $light_gray:#eee;
.svg-container { .svg-container {
padding: 6px 5px 6px 15px; padding: 6px 5px 6px 15px;
color: $dark_gray; // color: $dark_gray;
vertical-align: middle; vertical-align: middle;
width: 30px; width: 30px;
display: inline-block; display: inline-block;
@ -217,8 +237,8 @@ $light_gray:#eee;
.title { .title {
font-size: 26px; font-size: 26px;
color: $light_gray; color: #0174d7;
margin: 0px auto 40px auto; margin: 0px auto 20px auto;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
} }
@ -229,7 +249,7 @@ $light_gray:#eee;
right: 10px; right: 10px;
top: 7px; top: 7px;
font-size: 16px; font-size: 16px;
color: $dark_gray; // color: $dark_gray;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
} }

View File

@ -11,18 +11,31 @@
max-height="600" max-height="600"
> >
<el-table-column type="index" width="50"></el-table-column> <el-table-column type="index" width="50"></el-table-column>
<el-table-column align="header-center" label="账户"> <el-table-column label="账户">
<template slot-scope="scope">{{ scope.row.username }}</template> <template slot-scope="scope">{{ scope.row.username }}</template>
</el-table-column> </el-table-column>
<el-table-column align="header-center" label="姓名"> <el-table-column label="姓名">
<template slot-scope="scope">{{ scope.row.name }}</template> <template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column> </el-table-column>
<el-table-column label="角色">
<template slot-scope="scope">
<el-tag v-for="item in scope.row.roles_" v-bind:key="item" effect="plain">
{{item}}
</el-tag>
</template>
</el-table-column>
<el-table-column label="所属省份">
<template slot-scope="scope">{{ scope.row.pname }}</template>
</el-table-column>
<el-table-column label="所属单位">
<template slot-scope="scope">{{ scope.row.bcompany_name }}</template>
</el-table-column>
<el-table-column label="创建日期"> <el-table-column label="创建日期">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.date_joined }}</span> <span>{{ scope.row.date_joined }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="操作"> <el-table-column label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
type="primary" type="primary"
@ -76,12 +89,38 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="省份" prop="pname">
<el-select placeholder="请选择" clearable v-model="user.pname" style="width:100%">
<el-option
v-for="item in poptions"
:key="item.label"
:label="item.label"
:value="item.label"
style="width:100%"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="单位" prop="bcompany">
<el-input placeholder="单位" v-model="user.bcompany_name" readonly>
<el-button slot="append" icon="el-icon-search" @click="dgcVisiable=true"></el-button>
</el-input>
</el-form-item>
</el-form> </el-form>
<div style="text-align:right;"> <div style="text-align:right;">
<el-button type="danger" @click="dialogVisible=false">取消</el-button> <el-button type="danger" @click="dialogVisible=false">取消</el-button>
<el-button type="primary" @click="confirmUser('userForm')">确认</el-button> <el-button type="primary" @click="confirmUser('userForm')">确认</el-button>
</div> </div>
</el-dialog> </el-dialog>
<el-dialog
title="选择企业"
:visible.sync="dgcVisiable"
:close-on-click-modal="false"
width="80%"
:append-to-body="true"
>
<Companychose ref="Companychose" @handleChose="chooseComplete"></Companychose>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
@ -89,6 +128,8 @@ import { getUserList, createUser, deleteUser, updateUser} from "@/api/user";
import { getRoles } from "@/api/role" import { getRoles } from "@/api/role"
import checkPermission from "@/utils/permission"; import checkPermission from "@/utils/permission";
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
import { provinceAndCityData } from 'element-china-area-data'
import Companychose from "@/views/crm/companychose";
const defaultUser = { const defaultUser = {
id: "", id: "",
@ -97,7 +138,7 @@ const defaultUser = {
is_superuser:false is_superuser:false
}; };
export default { export default {
components: { Pagination }, components: { Pagination, Companychose },
data() { data() {
return { return {
user: defaultUser, user: defaultUser,
@ -117,7 +158,9 @@ export default {
treeLoding: false, treeLoding: false,
orgData: [], orgData: [],
dialogType:'create', dialogType:'create',
dialogVisible:false dialogVisible:false,
poptions: provinceAndCityData,
dgcVisiable:false
}; };
}, },
computed: {}, computed: {},
@ -154,6 +197,13 @@ export default {
this.dialogType = 'update' this.dialogType = 'update'
} , } ,
chooseComplete(val){
this.dgcVisiable = false;
if (val) {
this.user.bcompany_name = val.name;
this.user.bcompany = val.id;
}
},
handleDelete(scope) { handleDelete(scope) {
this.$confirm("确认删除?", "警告", { this.$confirm("确认删除?", "警告", {
confirmButtonText: "确认", confirmButtonText: "确认",

View File

@ -52,7 +52,11 @@
show-checkbox show-checkbox
node-key="id" node-key="id"
class="permission-tree" class="permission-tree"
/> >
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}-{{ data.method }}</span>
</span>
</el-tree>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div style="text-align:right;"> <div style="text-align:right;">

View File

@ -217,6 +217,7 @@ import { upUrl } from "@/api/file";
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
const defaultUser = { const defaultUser = {
id: "", id: "",
name: "", name: "",
@ -364,6 +365,7 @@ export default {
console.error(err); console.error(err);
}); });
}, },
async confirmUser(form) { async confirmUser(form) {
this.$refs[form].validate(valid => { this.$refs[form].validate(valid => {
if (valid) { if (valid) {

View File

@ -167,10 +167,18 @@ class CompanyViewSet(ModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = self.queryset queryset = self.queryset
if self.request.query_params.get('perm', None): if self.request.user.is_superuser:
return queryset return queryset
if not self.request.user.is_superuser: roles = self.request.user.roles.values_list('name', flat=True)
queryset = queryset.filter(create_admin = self.request.user) if '普通管理' in roles:
queryset = queryset.filter(create_admin = self.request.user)
elif '省管理' in roles:
if self.request.user.pname:
queryset = queryset.filter(geo__pname = self.request.user.pname)
else:
return Company.objects.none()
else:
return queryset.none()
return queryset return queryset
@action(methods=['put'], detail=True, url_name='company_transfer',perms_map=[{'*':'company_transfer'}]) @action(methods=['put'], detail=True, url_name='company_transfer',perms_map=[{'*':'company_transfer'}])
@ -243,10 +251,25 @@ class ConsumerViewSet(ModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = self.queryset queryset = self.queryset
queryset = self.get_serializer_class().setup_eager_loading(queryset) queryset = self.get_serializer_class().setup_eager_loading(queryset)
if self.request.user.is_superuser:
return queryset
roles = self.request.user.roles.values_list('name', flat=True)
if '普通管理' in roles:
queryset = queryset.filter(create_admin = self.request.user)
elif '省管理' in roles:
if self.request.user.pname:
queryset = queryset.filter(company__geo__pname = self.request.user.pname)
else:
return Consumer.objects.none()
elif '本单位管理' in roles:
if self.request.user.bcompany:
queryset = queryset.filter(company = self.request.user.bcompany)
else:
return Consumer.objects.none()
else:
return queryset.none()
if self.request.query_params.get('adminoff', None): if self.request.query_params.get('adminoff', None):
return queryset.filter(create_admin=None) return queryset.filter(create_admin=None)
if not self.request.user.is_superuser:
queryset = queryset.filter(create_admin = self.request.user)
return queryset return queryset
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):

View File

@ -48,10 +48,26 @@ class ExamViewSet(ModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = Exam.objects.all() queryset = Exam.objects.all()
if not self.request.user.is_superuser:
queryset = queryset.filter(create_admin = self.request.user)
if hasattr(self.get_serializer_class(), 'setup_eager_loading'): if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset) # 性能优化 queryset = self.get_serializer_class().setup_eager_loading(queryset) # 性能优化
if self.request.user.is_superuser:
return queryset
roles = self.request.user.roles.values_list('name', flat=True)
if '普通管理' in roles:
queryset = queryset.filter(create_admin = self.request.user)
elif '省管理' in roles:
if self.request.user.pname:
queryset = queryset.filter(examtest_exam__consumer__company__geo__pname = self.request.user.pname)
else:
return queryset.objects.none()
elif '本单位管理' in roles:
if self.request.user.bcompany:
queryset = queryset.filter(examtest_exam__consumer__company = self.request.user.bcompany)
else:
return queryset.objects.none()
else:
return queryset.none()
return queryset return queryset
def get_serializer_class(self): def get_serializer_class(self):
@ -353,24 +369,39 @@ class ExamTestViewSet(ModelViewSet):
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ['type','is_pass', 'exam'] filterset_fields = ['type','is_pass', 'exam']
def get_queryset(self): def filter_queryset(self, queryset):
assert self.queryset is not None, ( for backend in list(self.filter_backends):
"'%s' should either include a `queryset` attribute, " queryset = backend().filter_queryset(self.request, queryset, self)
"or override the `get_queryset()` method." if self.request.query_params.get('start'):
% self.__class__.__name__ queryset = queryset.filter(start_time__gte=self.request.query_params['start'] )
) if self.request.query_params.get('end'):
queryset = self.queryset queryset = queryset.filter(start_time__lte=self.request.query_params['end'])
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
if self.request.query_params.get('start'):
queryset = queryset.filter(start_time__gte=self.request.query_params['start'] )
if self.request.query_params.get('end'):
queryset = queryset.filter(start_time__lte=self.request.query_params['end'])
if not self.request.user.is_superuser:
queryset = queryset.filter(Q(consumer__create_admin = self.request.user)|Q(exam__create_admin=self.request.user))
return queryset return queryset
def get_queryset(self):
queryset = self.queryset
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset)
if self.request.user.is_superuser:
return queryset
roles = self.request.user.roles.values_list('name', flat=True)
if '普通管理' in roles:
queryset = queryset.filter(Q(consumer__create_admin = self.request.user)|Q(exam__create_admin=self.request.user))
elif '省管理' in roles:
if self.request.user.pname:
queryset = queryset.filter(consumer__company__geo__pname = self.request.user.pname)
else:
return queryset.objects.none()
elif '本单位管理' in roles:
if self.request.user.bcompany:
queryset = queryset.filter(consumer__company = self.request.user.bcompany)
else:
return queryset.objects.none()
else:
return queryset.none()
return queryset
@action(methods=['get'], detail=False,url_path='self', url_name='selftest', perms_map = [{'*':'my_examtest'}]) @action(methods=['get'], detail=False,url_path='self', url_name='selftest', perms_map = [{'*':'my_examtest'}])
def selftest(self, request, pk=None): def selftest(self, request, pk=None):
''' '''

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.4 on 2021-04-05 10:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rbac', '0003_auto_20200402_1157'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='pname',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='所属省份'),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 3.0.4 on 2021-04-05 13:01
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('crm', '0027_consumer_deptname'),
('rbac', '0004_userprofile_pname'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='bcompany',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='crm.Company', verbose_name='所属公司'),
),
]

View File

@ -109,7 +109,6 @@ class Role(SoftCommonModel):
name = models.CharField(max_length=32, unique=True, verbose_name="角色") name = models.CharField(max_length=32, unique=True, verbose_name="角色")
menus = models.ManyToManyField("Menu", blank=True, verbose_name="功能权限") menus = models.ManyToManyField("Menu", blank=True, verbose_name="功能权限")
desc = models.CharField(max_length=50, blank=True, null=True, verbose_name="描述") desc = models.CharField(max_length=50, blank=True, null=True, verbose_name="描述")
class Meta: class Meta:
verbose_name = "角色" verbose_name = "角色"
verbose_name_plural = verbose_name verbose_name_plural = verbose_name
@ -151,6 +150,9 @@ class UserProfile(AbstractUser):
roles = models.ManyToManyField("Role", verbose_name="角色", blank=True) roles = models.ManyToManyField("Role", verbose_name="角色", blank=True)
is_delete = models.BooleanField(default=False, verbose_name='删除标记', help_text='删除标记') is_delete = models.BooleanField(default=False, verbose_name='删除标记', help_text='删除标记')
pname = models.CharField('所属省份', max_length=100, null=True, blank=True)
bcompany = models.ForeignKey('crm.company', verbose_name='所属公司', null=True, blank=True, on_delete=models.SET_NULL)
class Meta: class Meta:
verbose_name = "用户信息" verbose_name = "用户信息"
verbose_name_plural = verbose_name verbose_name_plural = verbose_name

View File

View File

@ -10,6 +10,8 @@ class UserListSerializer(serializers.ModelSerializer):
# roles = serializers.SerializerMethodField() # roles = serializers.SerializerMethodField()
date_joined = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) date_joined = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
department_name = serializers.StringRelatedField(source='department') department_name = serializers.StringRelatedField(source='department')
roles_ = serializers.StringRelatedField(source='roles', many=True)
bcompany_name = serializers.StringRelatedField(source='bcompany')
# def get_roles(self, obj): # def get_roles(self, obj):
# return obj.roles.values() # return obj.roles.values()
@ -17,9 +19,16 @@ class UserListSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = UserProfile model = UserProfile
fields = ['id', 'username', 'name', 'department', 'position', fields = ['id', 'username', 'name', 'department', 'position',
'is_active', 'roles', 'date_joined', 'is_superuser','department_name', 'avatar'] 'is_active', 'roles', 'date_joined', 'is_superuser','department_name', 'avatar', 'roles_', 'pname', 'bcompany_name']
# depth = 1 # depth = 1
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.select_related('superior','department', 'bcompany')
queryset = queryset.prefetch_related('roles',)
return queryset
class UserModifySerializer(serializers.ModelSerializer): class UserModifySerializer(serializers.ModelSerializer):
""" """
@ -30,7 +39,7 @@ class UserModifySerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = UserProfile model = UserProfile
fields = ['id', 'username', 'name', 'mobile', 'email', 'avatar', 'department', 'position', 'superior', fields = ['id', 'username', 'name', 'mobile', 'email', 'avatar', 'department', 'position', 'superior',
'is_active', 'roles'] 'is_active', 'roles', 'pname', 'bcompany']
def validate_mobile(self, mobile): def validate_mobile(self, mobile):
REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|^176\d{8}$" REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|^176\d{8}$"
@ -49,7 +58,7 @@ class UserCreateSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = UserProfile model = UserProfile
fields = ['id', 'username', 'name', 'mobile', 'email', 'department', 'position', 'is_active', 'roles', fields = ['id', 'username', 'name', 'mobile', 'email', 'department', 'position', 'is_active', 'roles',
'password','is_superuser'] 'password','is_superuser', 'pname', 'bcompany']
def validate_username(self, username): def validate_username(self, username):
if UserProfile.objects.filter(username=username): if UserProfile.objects.filter(username=username):

View File

@ -77,6 +77,8 @@ class UserViewSet(PageOrNot, ModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = self.queryset queryset = self.queryset
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset) # 性能优化
department = self.request.query_params.get('department', None) # 该部门及其子部门所有员工 department = self.request.query_params.get('department', None) # 该部门及其子部门所有员工
name = self.request.query_params.get('name',None) name = self.request.query_params.get('name',None)
if name is not None: if name is not None: