Browse Source

Merge remote-tracking branch 'origin/master'

master
liutong 10 months ago
parent
commit
d0ec160f92
  1. 2
      admin/package.json
  2. 3
      admin/src/layout/default/components/aside/index.vue
  3. 19
      admin/src/layout/default/components/aside/menu-item.vue
  4. 14
      admin/src/layout/default/components/header/index.vue
  5. 4
      admin/src/stores/modules/system.ts
  6. 2
      niucloud/app/adminapi/route/person_course_schedule.php
  7. 8
      niucloud/app/event.php
  8. 180
      niucloud/app/listener/custom/CoachPerformanceListener.php
  9. 125
      niucloud/app/listener/custom/SalesPerformanceListener.php
  10. 3
      niucloud/app/service/admin/person_course_schedule/PersonCourseScheduleService.php

2
admin/package.json

@ -5,7 +5,7 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build && node publish.cjs", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"lint": "eslint .", "lint": "eslint .",
"lint:fix": "eslint . --ext .ts --ext .vue --ext .js --fix", "lint:fix": "eslint . --ext .ts --ext .vue --ext .js --fix",

3
admin/src/layout/default/components/aside/index.vue

@ -9,6 +9,9 @@
:with-header="false" :with-header="false"
custom-class="aside-drawer" custom-class="aside-drawer"
size="210px" size="210px"
:show-close="true"
:close-on-click-modal="true"
:close-on-press-escape="true"
> >
<template #default> <template #default>
<side /> <side />

19
admin/src/layout/default/components/aside/menu-item.vue

@ -20,7 +20,7 @@
<template v-if="addonsMenus"> <template v-if="addonsMenus">
<menu-item <menu-item
:routes="addonsMenus" :routes="addonsMenus"
:key="index" :key="'addon'"
:level="props.level + 1" :level="props.level + 1"
/> />
</template> </template>
@ -29,7 +29,7 @@
<template v-else> <template v-else>
<el-menu-item <el-menu-item
:index="String(routes.name)" :index="String(routes.name)"
@click="router.push({ name: routes.name })" @click="handleMenuClick(routes.name)"
v-if="meta.addon && meta.parent_route && meta.parent_route.addon == ''" v-if="meta.addon && meta.parent_route && meta.parent_route.addon == ''"
> >
<template #title> <template #title>
@ -53,7 +53,7 @@
</el-menu-item> </el-menu-item>
<el-menu-item <el-menu-item
:index="String(routes.name)" :index="String(routes.name)"
@click="router.push({ name: routes.name })" @click="handleMenuClick(routes.name)"
v-else v-else
> >
<template #title> <template #title>
@ -99,6 +99,19 @@ const props = defineProps({
const systemStore = useSystemStore() const systemStore = useSystemStore()
const meta = computed(() => props.routes.meta) const meta = computed(() => props.routes.meta)
//
const handleMenuClick = (name: string | number) => {
//
router.push({ name: name.toString() })
//
if (window.innerWidth < 768) {
systemStore.$patch((state) => {
state.menuDrawer = false
})
}
}
const addons = computed(() => { const addons = computed(() => {
const addons: Record<string, any> = {} const addons: Record<string, any> = {}
systemStore?.apps.forEach((item: any) => { systemStore?.apps.forEach((item: any) => {

14
admin/src/layout/default/components/header/index.vue

@ -37,16 +37,6 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<div class="right-panel h-full flex items-center justify-end"> <div class="right-panel h-full flex items-center justify-end">
<!-- 预览 只有站点时展示-->
<i
class="iconfont iconicon_huojian1 cursor-pointer px-[8px]"
:title="t('visitWap')"
@click="toPreview"
></i>
<!-- 切换语言 -->
<div class="navbar-item flex items-center h-full cursor-pointer">
<switch-lang />
</div>
<!-- 切换全屏 --> <!-- 切换全屏 -->
<!-- <div class="navbar-item flex items-center h-full cursor-pointer" @click="toggleFullscreen"> <!-- <div class="navbar-item flex items-center h-full cursor-pointer" @click="toggleFullscreen">
<icon name="iconfont icontuichuquanping" v-if="isFullscreen" /> <icon name="iconfont icontuichuquanping" v-if="isFullscreen" />
@ -158,8 +148,10 @@ onMounted(() => {
// //
const toggleMenuCollapse = () => { const toggleMenuCollapse = () => {
systemStore.$patch((state) => { systemStore.$patch((state) => {
console.log('toggleMenuCollapse',screenWidth.value)
if (screenWidth.value < 768) { if (screenWidth.value < 768) {
state.menuDrawer = true //
state.menuDrawer = !state.menuDrawer
state.menuIsCollapse = false state.menuIsCollapse = false
} else { } else {
systemStore.toggleMenuCollapse(!systemStore.menuIsCollapse) systemStore.toggleMenuCollapse(!systemStore.menuIsCollapse)

4
admin/src/stores/modules/system.ts

@ -6,6 +6,7 @@ import { getInstalledAddonList } from '@/app/api/addon'
interface System { interface System {
menuIsCollapse: boolean menuIsCollapse: boolean
menuDrawer: boolean
dark: boolean dark: boolean
theme: string theme: string
lang: string lang: string
@ -19,6 +20,7 @@ const useSystemStore = defineStore('system', {
state: (): System => { state: (): System => {
return { return {
menuIsCollapse: false, menuIsCollapse: false,
menuDrawer: false,
dark: theme.dark ?? false, dark: theme.dark ?? false,
theme: theme.theme ?? '#273de3', theme: theme.theme ?? '#273de3',
lang: storage.get('lang') ?? 'zh-cn', lang: storage.get('lang') ?? 'zh-cn',
@ -27,7 +29,7 @@ const useSystemStore = defineStore('system', {
} }
}, },
actions: { actions: {
setTheme(state: string, value: any) { setTheme(state: keyof Pick<System, 'dark' | 'theme'>, value: any) {
this[state] = value this[state] = value
theme[state] = value theme[state] = value
storage.set({ key: 'theme', data: theme }) storage.set({ key: 'theme', data: theme })

2
niucloud/app/adminapi/route/person_course_schedule.php

@ -34,6 +34,8 @@ Route::group('person_course_schedule', function () {
Route::get('customer_resources_all','person_course_schedule.PersonCourseSchedule/getCustomerResourcesAll'); Route::get('customer_resources_all','person_course_schedule.PersonCourseSchedule/getCustomerResourcesAll');
//获取试课人员
Route::get('get_try_course_person/:schedule_id', 'person_course_schedule.PersonCourseSchedule/getTryCoursePerson');
})->middleware([ })->middleware([
AdminCheckToken::class, AdminCheckToken::class,
AdminCheckRole::class, AdminCheckRole::class,

8
niucloud/app/event.php

@ -115,11 +115,17 @@ $system_event = [
'app\listener\system\ShowAppListener' 'app\listener\system\ShowAppListener'
], ],
//计算业绩 //计算市场人员业绩
'CalculatePerformance' => [ 'app\listener\personnel\CalculatePerformance' ], 'CalculatePerformance' => [ 'app\listener\personnel\CalculatePerformance' ],
//学员 //学员
'Student' => [ 'app\listener\personnel\Student' ], 'Student' => [ 'app\listener\personnel\Student' ],
//计算销售人员业绩
'SalesPerformance' => [ 'app\listener\custom\SalesPerformanceListener' ],
//计算教练业绩
'CoachPerformance' => [ 'app\listener\custom\CoachPerformanceListener' ],
], ],
'subscribe' => [ 'subscribe' => [
], ],

180
niucloud/app/listener/custom/CoachPerformanceListener.php

@ -0,0 +1,180 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\listener\custom;
use app\model\performance_records\PerformanceRecords;
use app\model\course\Course;
use app\model\personnel\Personnel;
use app\model\student\Student;
/**
* 计算教练业绩事件
* Class CoachPerformanceListener
* @package app\listener\custom
*/
class CoachPerformanceListener
{
/**
* 处理教练业绩计算
* @param array $params
* $params['course_id'] 课程ID
* $params['coach_id'] 教练ID
* $params['student_id'] 学员ID
* $params['performance_type'] 业绩类型,可选值:'course'=课程授课,'private'=私教,'assessment'=考核评估
*/
public function handle(array $params)
{
// 检查必要参数
if (empty($params['course_id']) || empty($params['coach_id'])) {
return false;
}
// 获取课程信息
$courseInfo = (new Course())->find($params['course_id']);
if (empty($courseInfo)) {
return false;
}
// 检查教练是否存在
$personnel = (new Personnel())->find($params['coach_id']);
if (empty($personnel)) {
return false;
}
// 业绩类型,默认为课程授课
$performanceType = $params['performance_type'] ?? 'course';
// 计算业绩值
$performanceValue = $this->calculatePerformanceValue($courseInfo, $performanceType, $params);
// 记录业绩
return $this->recordPerformance([
'staff_id' => $params['coach_id'],
'course_id' => $params['course_id'],
'student_id' => $params['student_id'] ?? 0,
'performance_type' => $performanceType,
'performance_value' => $performanceValue,
'remarks' => '系统自动计算教练业绩',
]);
}
/**
* 计算业绩值
* @param object $courseInfo 课程信息
* @param string $performanceType 业绩类型
* @param array $params 额外参数
* @return float 业绩值
*/
protected function calculatePerformanceValue($courseInfo, $performanceType, $params)
{
$value = 0;
// 获取课程时长(小时)
$courseDuration = floatval($courseInfo['duration'] ?? 1);
// 根据业绩类型计算业绩值
switch ($performanceType) {
case 'course':
// 普通课程授课业绩,按照课时和课程基础系数计算
$baseRate = 50; // 每小时基本业绩值
$value = $courseDuration * $baseRate;
// 如果有学员参数,增加学员数量系数
if (!empty($params['student_count'])) {
$studentCount = intval($params['student_count']);
// 每多一名学员,业绩系数增加5%
$studentFactor = 1 + (($studentCount - 1) * 0.05);
$value = $value * $studentFactor;
}
break;
case 'private':
// 私教课程业绩,私教课程通常有更高的业绩系数
$privateRate = 150; // 每小时私教业绩值
$value = $courseDuration * $privateRate;
// 检查学员等级,高级别学员可以提高业绩
if (!empty($params['student_id'])) {
$student = (new Student())->find($params['student_id']);
if (!empty($student) && !empty($student['level'])) {
// 根据学员等级增加业绩系数
$levelFactor = 1 + (intval($student['level']) * 0.1);
$value = $value * $levelFactor;
}
}
break;
case 'assessment':
// 考核评估业绩,固定业绩值加上考核难度系数
$assessmentBaseValue = 100; // 基础考核业绩值
$difficultyLevel = intval($params['difficulty_level'] ?? 1); // 难度等级1-5
$value = $assessmentBaseValue * $difficultyLevel;
break;
default:
// 默认按课时计算
$value = $courseDuration * 50;
}
return $value;
}
/**
* 记录业绩
* @param array $data 业绩数据
* @return bool
*/
protected function recordPerformance(array $data)
{
// 准备记录数据
$recordData = [
'staff_id' => $data['staff_id'],
'performance_type' => $data['performance_type'],
'performance_value' => $data['performance_value'],
'remarks' => $data['remarks']
];
// 如果有课程ID,记录到扩展字段
if (!empty($data['course_id'])) {
$recordData['extend_id'] = $data['course_id'];
$recordData['extend_type'] = 'course';
}
// 如果有学员ID,记录到相关字段
if (!empty($data['student_id'])) {
$recordData['resource_id'] = $data['student_id'];
}
// 查询是否已存在该课程的业绩记录
$exists = (new PerformanceRecords())->where([
['extend_id', '=', $data['course_id'] ?? 0],
['staff_id', '=', $data['staff_id']],
['performance_type', '=', $data['performance_type']]
])->find();
if ($exists) {
// 更新已有记录
return (new PerformanceRecords())->where('id', $exists['id'])->update([
'performance_value' => $data['performance_value'],
'remarks' => $data['remarks'],
'updated_at' => date('Y-m-d H:i:s')
]);
} else {
// 创建新记录
$recordData['created_at'] = date('Y-m-d H:i:s');
$recordData['updated_at'] = date('Y-m-d H:i:s');
$model = new PerformanceRecords();
$result = $model->create($recordData);
return !empty($result->id);
}
}
}

125
niucloud/app/listener/custom/SalesPerformanceListener.php

@ -0,0 +1,125 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\listener\custom;
use app\model\performance_records\PerformanceRecords;
use app\model\order_table\OrderTable;
use app\model\personnel\Personnel;
/**
* 计算销售人员业绩事件
* Class SalesPerformanceListener
* @package app\listener\custom
*/
class SalesPerformanceListener
{
/**
* 处理销售业绩计算
* @param array $params
* $params['order_id'] 订单ID
* $params['staff_id'] 销售人员ID
* $params['performance_type'] 业绩类型,可选值:'sales'=销售,'commission'=佣金
*/
public function handle(array $params)
{
// 检查必要参数
if (empty($params['order_id']) || empty($params['staff_id'])) {
return false;
}
// 获取订单信息
$orderInfo = (new OrderTable())->find($params['order_id']);
if (empty($orderInfo)) {
return false;
}
// 检查销售人员是否存在
$personnel = (new Personnel())->find($params['staff_id']);
if (empty($personnel)) {
return false;
}
// 业绩类型,默认为销售
$performanceType = $params['performance_type'] ?? 'sales';
// 计算业绩值
$performanceValue = $this->calculatePerformanceValue($orderInfo, $performanceType);
// 记录业绩
return $this->recordPerformance([
'staff_id' => $params['staff_id'],
'order_id' => $params['order_id'],
'resource_id' => $orderInfo['resource_id'] ?? 0,
'order_status' => $orderInfo['status'],
'performance_type' => $performanceType,
'performance_value' => $performanceValue,
'remarks' => '系统自动计算销售业绩',
]);
}
/**
* 计算业绩值
* @param object $orderInfo 订单信息
* @param string $performanceType 业绩类型
* @return float 业绩值
*/
protected function calculatePerformanceValue($orderInfo, $performanceType)
{
$value = 0;
// 根据订单金额和业绩类型计算业绩值
$orderAmount = floatval($orderInfo['total_amount'] ?? 0);
if ($performanceType == 'sales') {
// 销售业绩直接等于订单金额
$value = $orderAmount;
} elseif ($performanceType == 'commission') {
// 佣金业绩,假设为订单金额的10%
$commissionRate = 0.1; // 佣金比例,可以从配置中获取
$value = $orderAmount * $commissionRate;
}
return $value;
}
/**
* 记录业绩
* @param array $data 业绩数据
* @return bool
*/
protected function recordPerformance(array $data)
{
// 查询是否已存在该订单的业绩记录
$exists = (new PerformanceRecords())->where([
['order_id', '=', $data['order_id']],
['staff_id', '=', $data['staff_id']],
['performance_type', '=', $data['performance_type']]
])->find();
if ($exists) {
// 更新已有记录
return (new PerformanceRecords())->where('id', $exists['id'])->update([
'performance_value' => $data['performance_value'],
'order_status' => $data['order_status'],
'remarks' => $data['remarks'],
'updated_at' => date('Y-m-d H:i:s')
]);
} else {
// 创建新记录
$data['created_at'] = date('Y-m-d H:i:s');
$data['updated_at'] = date('Y-m-d H:i:s');
$model = new PerformanceRecords();
$result = $model->create($data);
return !empty($result->id);
}
}
}

3
niucloud/app/service/admin/person_course_schedule/PersonCourseScheduleService.php

@ -169,7 +169,8 @@ class PersonCourseScheduleService extends BaseAdminService
'student_id' => $student_id, 'student_id' => $student_id,
'person_type' => $student_id ? 'student' : 'customer_resource', 'person_type' => $student_id ? 'student' : 'customer_resource',
'course_date' => $schedule->course_date, 'course_date' => $schedule->course_date,
'time_slot' => $schedule->time_slot 'time_slot' => $schedule->time_slot,
'status' => 0,
]); ]);
} }

Loading…
Cancel
Save