renling
|
@ -94,6 +94,13 @@ export function unbindConsumer(id) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function claimConsumer(id) {
|
||||||
|
return request({
|
||||||
|
url: `/crm/consumer/${id}/claim/`,
|
||||||
|
method: 'put',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function getConsumerRoleAll(query) {
|
export function getConsumerRoleAll(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/crm/consumerrole/',
|
url: '/crm/consumerrole/',
|
||||||
|
|
|
@ -116,6 +116,12 @@ export const asyncRoutes = [
|
||||||
component: () => import('@/views/crm/consumer.vue'),
|
component: () => import('@/views/crm/consumer.vue'),
|
||||||
meta: { title: '学员列表', icon: '', perms: ['consumer_view'] }
|
meta: { title: '学员列表', icon: '', perms: ['consumer_view'] }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'claim',
|
||||||
|
name: 'Claim',
|
||||||
|
component: () => import('@/views/crm/claim.vue'),
|
||||||
|
meta: { title: '认领学员', icon: '', perms: ['consumer_view'] }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'consumerrule',
|
path: 'consumerrule',
|
||||||
name: 'ConsumerRule',
|
name: 'ConsumerRule',
|
||||||
|
|
|
@ -4,6 +4,7 @@ const getters = {
|
||||||
token: state => state.user.token,
|
token: state => state.user.token,
|
||||||
avatar: state => state.user.avatar,
|
avatar: state => state.user.avatar,
|
||||||
name: state => state.user.name,
|
name: state => state.user.name,
|
||||||
|
username: state=> state.user.username,
|
||||||
perms: state => state.user.perms,
|
perms: state => state.user.perms,
|
||||||
permission_routes: state => state.permission.routes
|
permission_routes: state => state.permission.routes
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<div>
|
||||||
|
<el-input
|
||||||
|
v-model="listQuery.username"
|
||||||
|
placeholder="手机号"
|
||||||
|
style="width: 200px;"
|
||||||
|
class="filter-item"
|
||||||
|
@keyup.enter.native="handleFilter"
|
||||||
|
/>
|
||||||
|
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||||
|
<el-button
|
||||||
|
class="filter-item"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-refresh-left"
|
||||||
|
@click="resetFilter"
|
||||||
|
>刷新重置</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
:data="consumerList"
|
||||||
|
style="width: 100%;margin-top:10px;"
|
||||||
|
border
|
||||||
|
fit
|
||||||
|
v-loading="listLoading"
|
||||||
|
highlight-current-row
|
||||||
|
max-height="600"
|
||||||
|
@sort-change="changeSort"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
|
|
||||||
|
<el-table-column label="姓名">
|
||||||
|
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="手机号" sortable="custom" prop="username">
|
||||||
|
<template slot-scope="scope">{{ scope.row.username }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="小程序OpenId" :show-overflow-tooltip="true">
|
||||||
|
<template slot-scope="scope">{{ scope.row.openid }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="用户类型">
|
||||||
|
<template slot-scope="scope">{{ scope.row.role_name }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="单位" sortable="custom" prop="company">
|
||||||
|
<template
|
||||||
|
slot-scope="scope"
|
||||||
|
v-if="scope.row.company_name != null"
|
||||||
|
>{{ scope.row.company_name }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="缴费学科">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-for="item in scope.row.subjects_name" :key="item">{{ item }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="工作类别" sortable="custom" prop="workscope">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.workscope_name">{{ scope.row.workscope_name }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建信息" sortable="custom" prop="create_time">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-if="scope.row.create_admin_">{{ scope.row.create_admin_.username }}/</span>
|
||||||
|
<span>{{ scope.row.create_time.substring(0,10) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="left" label="操作" fixed="right" width="260">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button-group>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="handleClaim(scope)"
|
||||||
|
:disabled="!checkPermission(['consumer_claim'])"
|
||||||
|
>认领</el-button>
|
||||||
|
</el-button-group>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="listQuery.page"
|
||||||
|
:limit.sync="listQuery.limit"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getConsumerList,
|
||||||
|
claimConsumer
|
||||||
|
} from "@/api/crm";
|
||||||
|
|
||||||
|
import { genTree, deepClone } from "@/utils";
|
||||||
|
import checkPermission from "@/utils/permission";
|
||||||
|
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
||||||
|
|
||||||
|
const listQuery = {
|
||||||
|
page: 1,
|
||||||
|
limit: 20,
|
||||||
|
adminoff: true,
|
||||||
|
};
|
||||||
|
export default {
|
||||||
|
components: { Pagination },
|
||||||
|
watch: {
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
consumerList: [],
|
||||||
|
total: 0,
|
||||||
|
listLoading: true,
|
||||||
|
listQuery: {
|
||||||
|
page: 1,
|
||||||
|
limit: 20,
|
||||||
|
adminoff: true,
|
||||||
|
},
|
||||||
|
selects: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
watch: {
|
||||||
|
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeSort(val) {
|
||||||
|
if (val.order == "ascending") {
|
||||||
|
this.listQuery.ordering = val.prop;
|
||||||
|
} else {
|
||||||
|
this.listQuery.ordering = "-" + val.prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
let selects = [];
|
||||||
|
for (var i = 0; i < val.length; i++) {
|
||||||
|
selects.push(val[i].id);
|
||||||
|
}
|
||||||
|
this.selects = selects;
|
||||||
|
},
|
||||||
|
checkPermission,
|
||||||
|
getList() {
|
||||||
|
this.listLoading = true;
|
||||||
|
getConsumerList(this.listQuery).then((response) => {
|
||||||
|
this.consumerList = response.data.results;
|
||||||
|
this.total = response.data.count;
|
||||||
|
this.listLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
resetFilter() {
|
||||||
|
this.listQuery = {
|
||||||
|
page: 1,
|
||||||
|
limit: 20,
|
||||||
|
adminoff: true,
|
||||||
|
};
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handleFilter() {
|
||||||
|
this.listQuery.page = 1;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handleClaim(scope) {
|
||||||
|
this.$confirm("确定认领该用户吗?", "提示", {
|
||||||
|
}).then(()=>{
|
||||||
|
claimConsumer(scope.row.id).then(res=>{
|
||||||
|
this.$message.success('认领成功')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -182,11 +182,11 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建信息" sortable="custom" prop="create_time" v-if="showCreate">
|
<el-table-column label="创建信息" sortable="custom" prop="create_time" v-if="showCreate">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.create_admin_.username }}/</span>
|
<span v-if="scope.row.create_admin_">{{ scope.row.create_admin_.username }}/</span>
|
||||||
<span>{{ scope.row.create_time.substring(0,10) }}</span>
|
<span>{{ scope.row.create_time.substring(0,10) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="left" label="操作" fixed="right" width="200">
|
<el-table-column align="left" label="操作" fixed="right" width="260">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button-group>
|
<el-button-group>
|
||||||
<el-button
|
<el-button
|
||||||
|
|
|
@ -69,9 +69,9 @@ App({
|
||||||
globalData: {
|
globalData: {
|
||||||
userInfo: {},
|
userInfo: {},
|
||||||
userinfo: {}, // 服务器传回的消费者信息
|
userinfo: {}, // 服务器传回的消费者信息
|
||||||
//host: 'https://apitest.ahctc.cn',
|
host: 'https://apitest.ahctc.cn',
|
||||||
mediahost: 'https://apitest.ahctc.cn',
|
mediahost: 'https://apitest.ahctc.cn',
|
||||||
host: 'http://127.0.0.1:8000',
|
//host: 'http://127.0.0.1:8000',
|
||||||
//mediahost: 'http://127.0.0.1:8000',
|
//mediahost: 'http://127.0.0.1:8000',
|
||||||
token : '',
|
token : '',
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 902 B After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 902 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 688 B After Width: | Height: | Size: 808 B |
After Width: | Height: | Size: 688 B |
Before Width: | Height: | Size: 808 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
|
@ -68,9 +68,20 @@ Page({
|
||||||
|
|
||||||
getDetail: function (id) {
|
getDetail: function (id) {
|
||||||
var that = this
|
var that = this
|
||||||
|
wx.showLoading({
|
||||||
|
title: '加载中',
|
||||||
|
mask:true
|
||||||
|
})
|
||||||
api.request(`/cms/article/${id}/`,'GET').then(res => {
|
api.request(`/cms/article/${id}/`,'GET').then(res => {
|
||||||
// res.data.content = res.data.content.replace(/"media/g, '"'+getApp().globalData.mediahost + '/media').replace(/\<img/gi, '<img style="max-width:100%;height:auto" ')
|
// res.data.content = res.data.content.replace(/"media/g, '"'+getApp().globalData.mediahost + '/media').replace(/\<img/gi, '<img style="max-width:100%;height:auto" ')
|
||||||
that.setData(res.data)
|
that.setData(res.data)
|
||||||
|
wx.hideLoading({
|
||||||
|
complete: (res) => {},
|
||||||
|
})
|
||||||
|
}).catch(res=>{
|
||||||
|
wx.hideLoading({
|
||||||
|
complete: (res) => {},
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1 +1,7 @@
|
||||||
/* pages/article/detail.wxss */
|
/* pages/article/detail.wxss */
|
||||||
|
.weui-article {
|
||||||
|
padding: 0px 12px;
|
||||||
|
}
|
||||||
|
.page__title {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="weui-panel__ft weui-cell__ft_in-access">
|
<view class="weui-panel__ft weui-cell__ft_in-access">
|
||||||
<view class="weui-media-box__desc">查看详情</view>
|
|
||||||
</view>
|
</view>
|
||||||
</navigator>
|
</navigator>
|
||||||
</block>
|
</block>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
"disablePlugins": [],
|
"disablePlugins": [],
|
||||||
"outputPath": ""
|
"outputPath": ""
|
||||||
},
|
},
|
||||||
"useCompilerModule": false,
|
"useCompilerModule": true,
|
||||||
"userConfirmedUseCompilerModuleSwitch": false,
|
"userConfirmedUseCompilerModuleSwitch": false,
|
||||||
"compileHotReLoad": false,
|
"compileHotReLoad": false,
|
||||||
"useIsolateContext": true
|
"useIsolateContext": true
|
||||||
|
|
|
@ -8,4 +8,4 @@ class ConsumerFilter(filters.FilterSet):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Consumer
|
model = Consumer
|
||||||
fields = ['company', 'role', 'min_create', 'max_create', 'create_admin']
|
fields = ['company', 'role', 'min_create', 'max_create', 'create_admin', 'username']
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Generated by Django 3.0.4 on 2020-08-26 06:44
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('crm', '0022_consumer_exceed_date'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='consumer',
|
||||||
|
name='create_admin',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
|
@ -72,7 +72,7 @@ class Consumer(CommonModel):
|
||||||
ID_number = models.CharField('身份证号', max_length=100, null=True, blank=True)
|
ID_number = models.CharField('身份证号', max_length=100, null=True, blank=True)
|
||||||
realname = models.CharField('真实姓名', max_length=100, null=True, blank=True)
|
realname = models.CharField('真实姓名', max_length=100, null=True, blank=True)
|
||||||
|
|
||||||
create_admin = models.ForeignKey(UserProfile, default=1, on_delete=models.DO_NOTHING)
|
create_admin = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
exceed_date = models.DateField('账号过期', null=True, blank=True)
|
exceed_date = models.DateField('账号过期', null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,8 @@ 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.query_params.get('adminoff', None):
|
||||||
|
return queryset.filter(create_admin=None)
|
||||||
if not self.request.user.is_superuser:
|
if not self.request.user.is_superuser:
|
||||||
queryset = queryset.filter(create_admin = self.request.user)
|
queryset = queryset.filter(create_admin = self.request.user)
|
||||||
return queryset
|
return queryset
|
||||||
|
@ -278,6 +280,7 @@ class ConsumerViewSet(ModelViewSet):
|
||||||
request.user.save()
|
request.user.save()
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
@action(methods=['get'], detail=False,
|
@action(methods=['get'], detail=False,
|
||||||
url_path='candidate', url_name='consumer_candidate', perms_map=[{'*':'*'}])
|
url_path='candidate', url_name='consumer_candidate', perms_map=[{'*':'*'}])
|
||||||
def candidate(self, request):
|
def candidate(self, request):
|
||||||
|
@ -420,6 +423,22 @@ class ConsumerViewSet(ModelViewSet):
|
||||||
Consumer.objects.exclude(exceed_date=None).update(exceed_date = datetime(2020,12,31))
|
Consumer.objects.exclude(exceed_date=None).update(exceed_date = datetime(2020,12,31))
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
@action(methods=['get'], detail=False,
|
||||||
|
url_path='correctadmin', url_name='correct_admin', perms_map=[{'*':'correct_admin'}])
|
||||||
|
def correctadmin(self, request):
|
||||||
|
Consumer.objects.filter(name='').update(create_admin=None)
|
||||||
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
@action(methods=['put'], detail=True, url_name='consumer_claim', perms_map=[{'*':'consumer_claim'}])
|
||||||
|
def claim(self, request, *args, **kwargs):
|
||||||
|
obj = self.get_object()
|
||||||
|
if obj.role.username and obj.create_admin is None:
|
||||||
|
obj.create_admin = request.user
|
||||||
|
obj.save()
|
||||||
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
else:
|
||||||
|
return Response({"error":"认领失败!"})
|
||||||
|
|
||||||
class ConsumerMPLoginView(APIView):
|
class ConsumerMPLoginView(APIView):
|
||||||
"""
|
"""
|
||||||
小程序登陆颁发token
|
小程序登陆颁发token
|
||||||
|
|
|
@ -302,9 +302,12 @@ class ExamTestViewSet(ModelViewSet):
|
||||||
def export(self, request):
|
def export(self, request):
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
queryset = ExamTestListSerializer.setup_eager_loading(queryset) # 性能优化
|
queryset = ExamTestListSerializer.setup_eager_loading(queryset) # 性能优化
|
||||||
|
if queryset.count()>1000:
|
||||||
|
return Response({'error':'数据量超过1000,请筛选后导出!'})
|
||||||
serializer = ExamTestListSerializer(instance=queryset, many=True)
|
serializer = ExamTestListSerializer(instance=queryset, many=True)
|
||||||
path = export_test(serializer.data)
|
path = export_test(serializer.data)
|
||||||
return Response({'path': path})
|
return Response({'path': path})
|
||||||
|
|
||||||
class PaperViewSet(ModelViewSet):
|
class PaperViewSet(ModelViewSet):
|
||||||
"""
|
"""
|
||||||
押题卷增删改查
|
押题卷增删改查
|
||||||
|
|