This commit is contained in:
yaosen 2024-06-26 15:38:38 +08:00
parent 617cabbe4c
commit 2561809d84
18 changed files with 177 additions and 165 deletions

View File

@ -8,22 +8,11 @@ export function login(data) {
})
}
// 获取城市列表
export function getCityList() {
return request({
url: '/admin/city/getCityList',
method: 'get'
})
}
// 获取子集列表
export function getQaList(city_id) {
export function getQaList() {
return request({
url: '/admin/qa/getQaList',
method: 'get',
params: {
city_id
}
})
}
// 获取qa详情

View File

@ -129,7 +129,7 @@
<el-button v-if="QaShow" type="success" @click="drawer = false"> </el-button>
<el-button v-if="!QaShow" type="success" @click="QaShow = true"> </el-button>
<div v-if="QaShow" class="mod">
<el-button v-for="item in getCityList" style="width: 150px;" size="medium" type="primary" @click="getQaDetail(item.city_id)">
<el-button v-for="item in getQaList" style="width: 150px;" size="medium" type="primary" @click="getQaDetail(item)">
{{ item.city_name }}
</el-button>
</div>
@ -152,7 +152,7 @@ import Search from '@/components/HeaderSearch'
import { color } from 'echarts/lib/export'
import sidebar from '@/layout/components/Sidebar/index.vue'
import avatar from 'element-ui/packages/avatar'
import { getCityList, getQaList, getQaDetail } from '@/api/qa'
import { getQaList } from '@/api/qa'
import clickoutside from 'element-ui/src/utils/clickoutside'
export default {
directives: { clickoutside },
@ -189,7 +189,7 @@ export default {
imageUrl: false,
QaShow: true,
os: [],
getCityList: [],
getQaList: [],
times: [],
form: {
oldpwd: '',
@ -213,8 +213,8 @@ export default {
},
created() {
this.getworkstatus()
getCityList().then(res => {
this.getCityList = res.data
getQaList().then(res => {
this.getQaList = res.data
})
},
methods: {
@ -226,18 +226,16 @@ export default {
this.drawer = false
this.QaShow = true
},
getQaDetail(id) {
getQaDetail(id).then(res => {
this.QaInfo = res.data
if (!this.QaInfo) {
return this.$message({
message: '暂无QA问题',
type: 'warning',
duration: 1500
})
}
this.QaShow = false
})
getQaDetail(data) {
this.QaInfo = data
if (!this.QaInfo) {
return this.$message({
message: '暂无QA问题',
type: 'warning',
duration: 1500
})
}
this.QaShow = false
},
async logout() {
await this.$store.dispatch('user/logout')
@ -267,7 +265,7 @@ export default {
})
},
startWorks() {
this.$axios.post('/admin/work/startworks', { id: this.id }).then(res => {
this.$axios.post('/admin/admin/editInfo', { is_order: 1 }).then(res => {
console.log(res)
this.$message({
showClose: true,
@ -279,7 +277,7 @@ export default {
})
},
endWorks() {
this.$axios.post('/admin/work/endworks', { id: this.id }).then(res => {
this.$axios.post('/admin/admin/editInfo', { is_order: 0 }).then(res => {
console.log(res)
this.$message({
showClose: true,

View File

@ -98,7 +98,7 @@ export const asyncRoutes = [
component: () => import('@/views/onlines/online.vue'),
name: 'onlines',
meta: {
title: '在线客服列表',
title: '在线客服',
roles: ['admin']
}
}/*,

View File

@ -24,7 +24,7 @@
<el-table-column align="center" label="管理员" width="80" prop="admin.username" />
<el-table-column align="center" label="操作" width="100" prop="action_name" />
<el-table-column align="center" label="操作" width="120" prop="action_name" />
<el-table-column align="center" label="订单号" width="220" prop="orders.sn" />
<el-table-column align="center" label="产品" prop="orders.product_name" />

View File

@ -2,7 +2,7 @@
<div class="app-container">
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%">
<el-table-column align="center" label="ID" width="60" prop="id" />
<el-table-column align="center" label="姓名" width="80" prop="name" />
<el-table-column align="center" label="姓名" width="80" prop="username" />
<el-table-column align="center" label="状态" width="100">
<template slot-scope="scope">
<el-tag v-if="scope.row.isOnline === 0" type="border-card">下线</el-tag>
@ -15,22 +15,27 @@
<el-switch v-model="scope.row.isEndWork" :active-value="1" :inactive-value="0" @change="updateStatus(scope.row)" />
</template>
</el-table-column>
<el-table-column align="center" label="剩余限制订单数量" width="190">
<!-- <el-table-column align="center" label="剩余限制订单数量" width="190">
<template #default="scope">
<el-input-number v-model="scope.row.order_num" :max="9999999" :min="0" class="small-input-number" style="width: 160px; height: 36px;" @change="updateStatus(scope.row)" />
</template>
</el-table-column>
<el-table-column align="center" label="在线时长" width="80">
</el-table-column>-->
<el-table-column align="center" label="在线时长" width="120">
<template slot-scope="scope">
{{ Math.floor((scope.row.data ? scope.row.data.onlineTime : scope.row.onlineTime) / 3600) || '--' }} 分钟
{{ Math.floor((scope.row.data ? scope.row.data.onlineTime : scope.row.onlineTime) / 60) || '--' }} 分钟
</template>
</el-table-column>
<el-table-column width="138px" align="center" label="开始分单的时间">
<el-table-column width="138px" align="center" label="上线时间">
<template slot-scope="scope">
<span>{{ scope.row.start_work_time | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column width="138px" align="center" label="停止分单的时间">
<el-table-column width="138px" align="center" label="下线时间">
<template slot-scope="scope">
<span>{{ scope.row.last_work_time | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column width="138px" align="center" label="停止分单时间">
<template slot-scope="scope">
<span>{{ scope.row.end_work_time | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
</template>
@ -70,7 +75,7 @@ export default {
},
methods: {
getOnlineList() {
this.listLoading = true // /admin/admin/getOnlineList /admin/shortcutContent/list
this.listLoading = true
this.$axios.get('/admin/admin/getOnlineList', { params: this.listQuery }).then(response => {
this.list = response.data
this.listLoading = false

View File

@ -121,7 +121,7 @@
</el-table-column>
<el-table-column align="center" width="500px" label="标题" prop="product_name" />
<el-table-column width="138px" align="center" label="跟进备注" prop="remark" />
<el-table-column width="500px" align="center" label="跟进备注" prop="remark" />
<el-table-column align="center" label="联系人" width="120" prop="contact" />

View File

@ -20,7 +20,7 @@
<el-table v-loading="listLoading" :data="list" border highlight-current-row style="width: 100%">
<el-table-column align="center" label="产品名称" width="220" prop="product_name" />
<el-table-column align="center" label="产品名称" width="260" prop="product_name" />
<el-table-column align="center" label="平台" width="80" prop="os">
<template slot-scope="scope">

View File

@ -131,48 +131,28 @@ class AdminController extends base
public function getOnlineList(Request $request)
{
$list = [];
$todayStart = strtotime(date('Y-m-d'));
$todayEnd = $todayStart + 86399;
// 获取今天在线的记录
$onlines = Onlines::alias('o')
->field('o.*, a.id as admin_id, a.name') // 选择需要的字段
->join('admins a', 'o.admin_id = a.id', 'LEFT') // 关联admins表
->where('start','>=',$todayStart)
->where('end','<=',$todayEnd)
->select();
foreach ($onlines as $online) {
$adminId = $online->admin_id;
$list[$adminId]['id'] = $adminId;
$list[$adminId]['name'] = $online->name;
$list[$adminId]['onlineTime'] = $list[$adminId]['onlineTime'] ?? 0 + (($online->end ? $online->end : $todayEnd) - $online->start);
$list[$adminId]['isOnline'] = Redis::get('CRM:USER:ONLINE:'.$online->admin_id) ? 1 : 0;
}
$users = Admins::where('status',1)->select();
foreach ($users as $user){
$adminId = $user->id;
if (empty($list[$user->id])){
$list[$adminId]['id'] = $adminId;
$list[$adminId]['name'] = $user->name;
$list[$adminId]['onlineTime'] = 0;
$list[$adminId]['isOnline'] = 2;
}
if (!isset($list[$adminId]['isOnline'])){
$list[$adminId]['isOnline'] = 0;
}
// if ($user->is_order == 1 && $list[$adminId]['isOnline'] ==1){
$list[$adminId]['isEndWork'] = 0;
if ($user->is_order == 1){
$list[$adminId]['isEndWork'] = 1;//是否分单
}else{
$list[$adminId]['isEndWork'] = 0;
}
if (!empty($user->end_work_time)) {
$list[$adminId]['onlineTime'] = strtotime(date('Y-m-d H:i:00',$user->end_work_time)) - strtotime(date('Y-m-d H:i:00',$user->start_work_time));
}else{
$list[$adminId]['onlineTime'] = $user->last_work_time > 0 ? strtotime(date('Y-m-d H:i:00',$user->last_work_time)) - strtotime(date('Y-m-d H:i:00',$user->start_work_time)) : 0;
}
$list[$adminId]['start_work_time'] = $user->start_work_time;
$list[$adminId]['end_work_time'] = $user->end_work_time;
$list[$adminId]['last_work_time'] = $user->last_work_time;
$list[$adminId]['order_num'] = $user->order_num;
$list[$adminId]['id'] = $adminId;
$list[$adminId]['username'] = $user->username;
$list[$adminId]['isOnline'] = Redis::get('CRM:USER:ONLINE:'.$adminId) ? 1 : 0;
}
return $this->success(array_values($list));
@ -181,7 +161,15 @@ class AdminController extends base
public function editInfo(Request $request)
{
$post = $request->post();
if (empty($post['id'])) return $this->error(500, '参数错误');
if (empty($post['id'])){
$post['id'] = $request->admin->id;
}
$post['end_work_time'] = time();
if ($post['is_order'] == 1){
$post['end_work_time'] = 0;
}
try {
Admins::update($post);

View File

@ -1,14 +0,0 @@
<?php
namespace app\admin\controller;
use app\model\Citys;
use support\Request;
class CityController extends base
{
public function getCityList(Request $request){
$list = Citys::fieldRaw('city_id,city_name')->where('status','=',1)->order('sort','desc')->select();
return $this->success($list);
}
}

View File

@ -90,25 +90,29 @@ class IndexController extends base
public function orders(Request $request)
{
$order = Orders::where('sn','>',0)
->fieldRaw('
SUM(IF(status=0,1,0)) as wait,
SUM(IF(status=1,1,0)) as doing,
SUM(total_price) as total,
count(id) as `all`,
SUM(IF(asset_price>0 AND status=2,1,0)) as asset,
SUM(IF(asset_price>0 AND status=2,asset_price,0)) as asset_price,
SUM(CASE
WHEN (os = 1 AND STATUS = 5) OR (os = 3 AND STATUS = 4) OR (os = 2 AND STATUS = 1) THEN 1
ELSE 0
END) AS refund,
SUM(CASE
WHEN (os = 1 AND STATUS = 5) OR (os = 3 AND STATUS = 4) OR (os = 2 AND STATUS = 1) THEN actual_price
ELSE 0
END) AS refund_price
');
$order = Orders::where('admin_id', $request->admin->id)->fieldRaw('
SUM(IF(status=0,1,0)) as wait,
SUM(IF(status=1,1,0)) as doing,
SUM(total_price) as total,
count(id) as `all`,
SUM(IF(asset_price>0 AND status=2,1,0)) as asset,
SUM(IF(asset_price>0 AND status=2,asset_price,0)) as asset_price,
SUM(CASE
WHEN (os = 1 AND STATUS = 5) OR (os = 3 AND STATUS = 4) OR (os = 2 AND STATUS = 1) THEN 1
ELSE 0
END) AS refund,
SUM(CASE
WHEN (os = 1 AND STATUS = 5) OR (os = 3 AND STATUS = 4) OR (os = 2 AND STATUS = 1) THEN actual_price
ELSE 0
END) AS refund_price
')->find();
if ($request->admin->id !=1){
$order = $order->where('admin_id', $request->admin->id);
}
// Log::warning("=====",['sql'=>$order]);
$order = $order->find();
return $this->success([
'wait' => $order->wait ?? 0,
@ -191,7 +195,7 @@ class IndexController extends base
$limit = $request->get('limit', 10);
$product_name = $request->get('product_name');
$os = $request->get('os_status');
$list = Orders::where('admin_id',$request->admin->id)
$list = Orders::where('sn','>',0)
->fieldRaw('
os,product_name,
SUM(IF(status=0,1,0)) as wait,
@ -211,12 +215,17 @@ class IndexController extends base
')
->group('os,product_name')
->order('total desc');
if ($request->admin->id !=1){
$list = $list->where('admin_id', $request->admin->id);
}
if (!empty($os)){
$list = $list->where('os',$os);
}
if (!empty($product_name)){
$list = $list->where('product_name','like','%'.$product_name.'%');
}
$list = $list->paginate($limit);
return $this->success($list);
}

View File

@ -35,6 +35,12 @@ class LoginController extends base
return $this->error(1004,'管理员状态错误'); //管理员状态错误
}
// 记录当天第一次上线时间
if (date('Y-m-d') != date('Y-m-d',$admin->start_work_time)){
$admin->start_work_time = $time;
$admin->save();
}
$data = [
'id'=> $admin->id,
'username' => $admin->username,

View File

@ -11,6 +11,7 @@ use stdClass;
use support\Log;
use support\Redis;
use support\Request;
use think\facade\Db;
class OrderController extends base
{
@ -37,7 +38,7 @@ class OrderController extends base
->order('update_time','desc')
->order('id','desc');
if($status!==null && $status >= 0) {
if($status!=null && $status >= 0) {
$query->where('status', $status);
}
@ -304,7 +305,7 @@ class OrderController extends base
$query->where('order_id', $order_id);
}
if($status !== null) {
if($status != null) {
$query->where('status', $status);
}
@ -336,19 +337,38 @@ class OrderController extends base
if(empty($item)) return $this->error(2002, '订单没有找到');
if($item->admin_id == $admin_id) return $this->error(2002, '订单已经在账号上,不需要再拉取!');
$back = Backs::create([
//管理员不用审批
$status = 0;
if ($request->admin->is_super == 1 || $request->admin->id == 1){
$status = 1;
}
$backs = [
'order_id' => $item->id,
'admin_id' => $admin_id,
'admin' => $item->admin_id,
'apply_id' => $request->admin->id
]);
Logs::todo($item->id, $admin_id, 7);
'apply_id' => $request->admin->id,
'status' => $status
];
try {
Db::transaction(function() use ($backs,$item) {
Backs::create($backs);
Logs::todo($backs['order_id'], $backs['apply_id'], $backs['status'] == 1 ? 12 : 7,$item->sn);
if($back) {
return $this->success($back);
}else{
if ($backs['status'] == 1){//管理员审批处理
Orders::where('id', $backs['order_id'])->where('admin_id', $backs['admin'])->update(['admin_id'=> $backs['admin_id']]);
$other = Backs::where('order_id', $backs['order_id'])->where('status', 0)->lock()->select();
foreach($other as $o) {
Backs::where('id', $o->id)->where('status', 0)->update(['status' => 3]);
Logs::todo($o->order_id, $o->admin, 10); //取消其他转单需求
}
}
});
}catch (\Exception $e){
return $this->error(2003, '创建拉回记录失败了');
}
return $this->success(true);
}
public function toBack(Request $request) {
@ -363,19 +383,38 @@ class OrderController extends base
if(empty($item)) return $this->error(2002, '订单没有找到');
if($item->admin_id == $admin_id) return $this->error(2002, '订单已经在账号上,不需要再拉取!');
$back = Backs::create([
//管理员不用审批
$status = 0;
if ($request->admin->is_super == 1 || $request->admin->id == 1){
$status = 1;
}
$backs = [
'order_id' => $item->id,
'admin_id' => $admin_id,
'admin' => $item->admin_id,
'apply_id' => $request->admin->id
]);
Logs::todo($item->id, $admin_id, 7);
'apply_id' => $request->admin->id,
'status' => $status
];
try {
Db::transaction(function() use ($backs,$item) {
Backs::create($backs);
Logs::todo($backs['order_id'], $backs['apply_id'], $backs['status'] == 1 ? 12 : 7,$item->sn);
if($back) {
return $this->success($back);
}else{
if ($backs['status'] == 1){//管理员审批处理
Orders::where('id', $backs['order_id'])->where('admin_id', $backs['admin'])->update(['admin_id'=> $backs['admin_id']]);
$other = Backs::where('order_id', $backs['order_id'])->where('status', 0)->lock()->select();
foreach($other as $o) {
Backs::where('id', $o->id)->where('status', 0)->update(['status' => 3]);
Logs::todo($o->order_id, $o->admin, 10); //取消其他转单需求
}
}
});
}catch (\Exception $e){
return $this->error(2003, '创建拉回记录失败了');
}
return $this->success(true);
}
/**

View File

@ -9,24 +9,17 @@ class QaController extends base
{
public function getQaList(Request $request)
{
$cityId = $request->get('city_id');
$limit = $request->get('limit', 10);
if (empty($cityId)) return $this->error(2001, 'city_id cannot be empty!');
$list = Qas::fieldRaw('city_id,title,content')->where('city_id', $cityId)->paginate($limit);
$list = Qas::fieldRaw('city_name,title,content')->select();
return $this->success($list);
}
public function getQaDetail(Request $request)
{
$cityId = $request->get('city_id');
// $id = $request->get('id');
$id = $request->get('id');
if (empty($id)) return $this->error(2001, 'id data cannot be empty!');
if (empty($cityId)) return $this->error(2001, 'city_id cannot be empty!');
$data = Qas::fieldRaw('city_id,title,content')->where([/*'id' => $id, */'city_id' => $cityId])->find();
$data = Qas::fieldRaw('id,city_name,title,content')->find();
return $this->success($data);
}
@ -34,7 +27,7 @@ class QaController extends base
public function addQa(Request $request)
{
$post = $request->post();
if (empty($post['city_id'])) return $this->error(2001, 'city_id data cannot be empty!');
if (empty($post['city_name'])) return $this->error(2001, 'city_name data cannot be empty!');
if (empty($post['title'])) return $this->error(2001, 'title data cannot be empty!');
if (empty($post['content'])) return $this->error(2001, 'content data cannot be empty!');

View File

@ -15,15 +15,21 @@ class WatchController extends base
$datas = Admins::order('create_time desc')->select();
foreach ($datas as $data) {
$item = [];
//set admin/index/isWork
$watch = Redis::get('CRM:USER:ONLINE:WATCH:'.$data->id);
if (empty($data->start_work_time)){
$item['start_work_time'] = $nowTime;
//记录下线时间
if (!empty($watch) && ($nowTime - $watch) > 6*60){
$item['end_work_time'] = $watch + 5*60;
}
if (($nowTime - $watch) > 0 && ($nowTime - $watch) <= 6*60){
$item['end_work_time'] = $nowTime;
//实时更新在线时间
if (($nowTime - $watch) <= 6*60){
$item['last_work_time'] = $nowTime;
}
Log::warning('watchIsWork',['data'=>$item]);
//记录当天第一次上线时间 start_work_time admin/login/index
if (!empty($item)){
try {
Admins::where('id', $data->id)->update($item);
@ -33,7 +39,6 @@ class WatchController extends base
}
}
}
echo "========watchIsWork end======\n";
return;
}
}

View File

@ -168,20 +168,6 @@ class WorkController extends base
return $this->success($anchor->hidden(['password', 'remember_token']));
}
public function endworks(Request $request)
{
// Redis::set("CRM:USER:ENDWORK:".$request->admin->id,10*3600);
Admins::update(['id' => $request->admin->id, 'is_order' => 0, 'end_work_time' => time()]);
return $this->success(null);
}
public function startworks(Request $request)
{
// Redis::del("CRM:USER:ENDWORK:" . $request->admin->id);
Admins::update(['id' => $request->admin->id, 'is_order' => 1,'start_work_time' => time()]);
return $this->success(null);
}
public function getworkstatus(Request $request)
{
// $workstatus = Redis::get("CRM:USER:ENDWORK:" . $request->admin->id);

View File

@ -58,18 +58,24 @@ class SpiderMt extends Command
$_u->username = $u->id;
$us[] = $_u;
}*/
if ($u->order_num > 0){
/*if ($u->order_num > 0){
if ($u->order_num !== $this->order_num){
$data = Admins::where('id',$u->id)->find();
$num = $data['order_num'] - 1;
if ($num >= 0){
Admins::where('id',$u->id)->update(['order_num'=>$num]);
}
}
$_u = new stdClass();
$_u->username = $u->id;
$us[] = $_u;
if ($u->order_num != $this->order_num){
Admins::where('id',$u->id)->decrement('order_num',1);
}
}
}*/
$_u = new stdClass();
$_u->username = $u->id;
$us[] = $_u;
};
}
$this->_users = $us;
return $this->_users;
}
@ -250,6 +256,7 @@ class SpiderMt extends Command
$order->is_check = 1;
$order->check_sn = $json->check_sn;
$order->admin_id = $json->admin_id;
$order->give_time = time();
$back = $order->save();
} elseif (!empty($order) && $order->admin_id !== $json->admin_id) {
echo '订单不在自己的名下,并且分人了。';
@ -272,6 +279,7 @@ class SpiderMt extends Command
$item->admin_id = $json->admin_id;
$item->check_sn = $json->check_sn;
$item->is_check = 1;
$item->give_time = time();
$back = $item->save();
$order->is_change = $json->admin_id;

View File

@ -3,7 +3,7 @@ namespace app\model;
class Logs extends base{
const Actions = [1 => '查看电话', 2 => '核销订单', 3=> '核销订单', 4 => '分单', 5 => '加微信', 6 => '公海领取', 7 => '申请拉回订单', 8 => '确认拉单请求', 9 => '拒绝拉单请求', 10 => '取消拉单请求',11 => '核销失败'];
const Actions = [1 => '查看电话', 2 => '核销订单', 3=> '核销订单', 4 => '分单', 5 => '加微信', 6 => '公海领取', 7 => '申请拉回订单', 8 => '确认拉单请求', 9 => '拒绝拉单请求', 10 => '取消拉单请求',11 => '核销失败',12 => '管理员操作转单'];
public function getActionNameAttr($val) {
return self::Actions[$this->action] ?? '未知';
@ -14,7 +14,7 @@ class Logs extends base{
}
public function orders(){
return $this->belongsTo(Orders::class, 'admin_id');
return $this->belongsTo(Orders::class, 'order_id');
}
//查看详情

View File

@ -246,7 +246,7 @@ class Monitor
public function onWorkerStart()
{
// 每秒钟执行一次
new Crontab('*/1 * * * * *', function(){
new Crontab('1 * * * * *', function(){
WatchController::watchIsWork();
});
}