Browse Source

Merge branch 'master' of ssh://gitlab.frkj.cc:222/php/zhjwxt

master
王泽彦 10 months ago
parent
commit
3685fa89a2
  1. 12
      admin/src/app/api/customer_resources.ts
  2. 13
      admin/src/app/api/service_logs.js
  3. 8
      admin/src/app/views/customer_resource_changes/customer_resource_changes.vue
  4. 172
      admin/src/app/views/customer_resources/components/UserProfile.vue
  5. 122
      admin/src/app/views/customer_resources/components/log.vue
  6. 118
      admin/src/app/views/customer_resources/components/order_table.vue
  7. 131
      admin/src/app/views/customer_resources/components/student_courses.vue
  8. 15
      admin/src/app/views/customer_resources/customer_resources.vue
  9. 14
      admin/src/app/views/school_approval/process/index.vue
  10. 165
      admin/src/app/views/service_logs/service_logs.vue
  11. 88
      admin/src/app/views/student_course_usage/student_course_usage.vue
  12. 29
      niucloud/app/adminapi/controller/customer_resources/CustomerResources.php
  13. 10
      niucloud/app/adminapi/controller/school_approval/Process.php
  14. 39
      niucloud/app/adminapi/controller/service_logs/ServiceLogs.php
  15. 6
      niucloud/app/adminapi/controller/student_course_usage/StudentCourseUsage.php
  16. 5
      niucloud/app/adminapi/route/customer_resources.php
  17. 31
      niucloud/app/adminapi/route/service_logs.php
  18. 88
      niucloud/app/api/controller/apiController/ClassApi.php
  19. 6
      niucloud/app/api/controller/apiController/Course.php
  20. 119
      niucloud/app/api/controller/apiController/CustomerResourcesAuth.php
  21. 42
      niucloud/app/api/controller/apiController/PersonCourseSchedule.php
  22. 65
      niucloud/app/api/controller/apiController/PhysicalTest.php
  23. 7
      niucloud/app/api/controller/apiController/TeachingResearch.php
  24. 46
      niucloud/app/api/controller/apiController/Test.php
  25. 53
      niucloud/app/api/controller/apiController/UserFeedback.php
  26. 12
      niucloud/app/api/controller/upload/Upload.php
  27. 67
      niucloud/app/api/route/route.php
  28. 19
      niucloud/app/common.php
  29. 11
      niucloud/app/model/class_grade/ClassGrade.php
  30. 57
      niucloud/app/model/class_personnel_rel/ClassPersonnelRel.php
  31. 6
      niucloud/app/model/course/Course.php
  32. 12
      niucloud/app/model/course_schedule/CourseSchedule.php
  33. 7
      niucloud/app/model/customer_resources/CustomerResources.php
  34. 7
      niucloud/app/model/physical_test/PhysicalTest.php
  35. 44
      niucloud/app/model/service_logs/ServiceLogs.php
  36. 1
      niucloud/app/model/student/Student.php
  37. 160
      niucloud/app/service/admin/customer_resources/CustomerResourcesService.php
  38. 60
      niucloud/app/service/admin/service_logs/ServiceLogsService.php
  39. 28
      niucloud/app/service/admin/student_course_usage/StudentCourseUsageService.php
  40. 24
      niucloud/app/service/api/apiService/CommonService.php
  41. 43
      niucloud/app/service/api/apiService/CourseService.php
  42. 117
      niucloud/app/service/api/apiService/CustomerResourcesService.php
  43. 98
      niucloud/app/service/api/apiService/PersonCourseScheduleService.php
  44. 115
      niucloud/app/service/api/apiService/PhysicalTestService.php
  45. 95
      niucloud/app/service/api/apiService/TestService.php
  46. 156
      niucloud/app/service/api/apiService/jlClassService.php
  47. 24
      niucloud/app/service/school_approval/SchoolApprovalProcessService.php

12
admin/src/app/api/customer_resources.ts

@ -76,3 +76,15 @@ export function fpEdit(params: Record<string, any>) {
export function getWithCoachList(params: Record<string, any>) { export function getWithCoachList(params: Record<string, any>) {
return request.get('customer_resources/coach_person', { params }) return request.get('customer_resources/coach_person', { params })
} }
export function getLogList(params: Record<string, any>) {
return request.get('customer_resources/log_list', { params })
}
export function getStudentCoursesList(params: Record<string, any>) {
return request.get('customer_resources/student_courses', { params })
}
export function getOrderTableList(params: Record<string, any>) {
return request.get('customer_resources/order_table', { params })
}

13
admin/src/app/api/service_logs.js

@ -0,0 +1,13 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- service_logs
/**
*
* @param params
* @returns
*/
export function getServiceLogsList(params) {
return request.get(`service_logs/service_logs`, {params})
}

8
admin/src/app/views/customer_resource_changes/customer_resource_changes.vue

@ -76,6 +76,12 @@ import { useRoute } from 'vue-router'
const route = useRoute() const route = useRoute()
const pageName = route.meta.title const pageName = route.meta.title
const props = defineProps({
value: Number
})
console.log(props.value);
let customerResourceChangesTable = reactive({ let customerResourceChangesTable = reactive({
page: 1, page: 1,
limit: 10, limit: 10,
@ -83,7 +89,7 @@ let customerResourceChangesTable = reactive({
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
customer_resource_id: route.query.id, customer_resource_id: props.value ? props.value : route.query.id,
}, },
}) })

172
admin/src/app/views/customer_resources/components/UserProfile.vue

@ -0,0 +1,172 @@
<template>
<el-dialog
v-model="showDialog"
title="客户详情"
width="80%"
class="user-profile p-6"
:destroy-on-close="true"
>
<!-- 顶部用户信息 -->
<el-card class="mb-4">
<div class="flex items-center">
<el-avatar :size="60" class="mr-4" :src="user.headimg"/>
<div>
<h2 class="text-xl font-bold">{{ user.nickname }}</h2>
<div style="display: flex; gap: 200px;margin-top: 10px;">
<p>ID: U{{ user.member_id }}</p>
<p>电话: {{ user.mobile }}</p>
<p>住址: {{ user.address }}</p>
</div>
</div>
</div>
</el-card>
<!-- 标签导航 -->
<el-tabs v-model="activeTab" class="mb-4">
<el-tab-pane label="六要素" name="six-elements" />
<el-tab-pane label="修改日志" name="log" />
<el-tab-pane label="学生情况" name="student" />
<el-tab-pane label="订单列表" name="orders" />
</el-tabs>
<!-- 六要素信息卡片 -->
<el-card v-if="activeTab === 'six-elements'">
<h3 class="text-lg font-bold mb-4">六要素信息</h3>
<el-row :gutter="20" class="mb-2">
<el-col :span="12">需求购买力<el-tag>{{ info.purchasePower }}</el-tag></el-col>
<el-col :span="12">认知理念<el-tag>{{ info.knowledge }}</el-tag></el-col>
</el-row>
<el-row :gutter="20" class="mb-2">
<el-col :span="12">距离<span>{{ info.distance }}</span></el-col>
<el-col :span="12">可谈上课时间<span>{{ info.canTalkDate }}</span></el-col>
</el-row>
<el-row :gutter="20" class="mb-2">
<el-col :span="12">承诺到访时间<span>{{ info.promisedVisitDate }}</span></el-col>
<el-col :span="12">实际到访时间<span>{{ info.actualVisitDate }}</span></el-col>
</el-row>
<el-row :gutter="20" class="mb-2">
<el-col :span="12">电话后的意向程度<el-tag>{{ info.phoneIntention }}</el-tag></el-col>
<el-col :span="12">是否关单
<el-tag :type="info.isClosed ? 'success' : 'danger'">{{ info.isClosed ? '是' : '否' }}</el-tag>
</el-col>
</el-row>
<!-- 备注与访问情况 -->
<el-form label-position="top" class="mt-4">
<el-form-item label="沟通备注">
<el-input v-model="info.notes" placeholder="填写备注" disabled/>
</el-form-item>
<el-form-item label="一访情况">
<el-input v-model="info.visit1" placeholder="填写一访情况" disabled/>
</el-form-item>
<el-form-item label="二访情况">
<el-input v-model="info.visit2" placeholder="填写二访情况" disabled/>
</el-form-item>
</el-form>
</el-card>
<el-card v-if="activeTab === 'log'">
<log :value="user.id"/>
</el-card>
<el-card v-if="activeTab === 'student'">
<student :value="user.id"/>
</el-card>
<el-card v-if="activeTab === 'orders'">
<orders :value="user.id"/>
</el-card>
</el-dialog>
</template>
<script setup>
import { useDictionary } from '@/app/api/dict'
import { ref, reactive, computed, watch } from 'vue'
import Log from '@/app/views/customer_resources/components/log.vue'
import Student from '@/app/views/customer_resources/components/student_courses.vue'
import Orders from '@/app/views/customer_resources/components/order_table.vue'
let showDialog = ref(false)
const activeTab = ref('six-elements')
const user = reactive({
id: '',
member_id:'',
nickname: '',
headimg: '',
mobile:'',
address:''
})
const info = reactive({
purchasePower: '',
knowledge: '',
distance: '',
canTalkDate: '',
promisedVisitDate: '',
actualVisitDate: '',
phoneIntention: '',
isClosed: '',
notes: '',
visit1: '',
visit2: ''
})
let call_intentList = ref([])
let purchase_powerList = ref([])
let concept_awarenessList = ref([])
const setFormData = async (row) => {
call_intentList.value = await (
await useDictionary('preliminarycustomerintention')
).data.dictionary
purchase_powerList.value = await (
await useDictionary('customer_purchasing_power')
).data.dictionary
concept_awarenessList.value = await (
await useDictionary('cognitive_concept')
).data.dictionary
user.id = row.id;
user.nickname = row.member_info.nickname;
user.member_id = row.member_info.member_id;
user.headimg = row.member_info.headimg;
user.mobile = row.member_info.mobile;
user.address = row.member_info.address;
info.purchasePower = purchase_powerList.value.flat().find(item => item.value == row.six.purchase_power)?.name || '';
info.knowledge = concept_awarenessList.value.flat().find(item => item.value == row.six.concept_awareness)?.name || '';
info.distance = row.six.distance;
info.canTalkDate = row.six.preferred_class_time;
info.promisedVisitDate = row.six.promised_visit_time;
info.actualVisitDate = row.six.actual_visit_time;
info.phoneIntention = call_intentList.value.flat().find(item => item.value == row.six.call_intent)?.name || '';
info.isClosed = row.six.is_closed == 1 ? true : false;
info.notes = row.six.communication;
info.visit1 = row.six.first_visit_status;
info.visit2 = row.six.second_visit_status;
console.log(call_intentList.value);
}
defineExpose({
showDialog,
setFormData
})
</script>
<style scoped>
.user-profile {
margin: 0 auto;
}
</style>

122
admin/src/app/views/customer_resources/components/log.vue

@ -0,0 +1,122 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
</div>
<div class="mt-[10px]">
<el-table
:data="customerResourceChangesTable.data"
size="large"
v-loading="customerResourceChangesTable.loading"
>
<template #empty>
<span>{{
!customerResourceChangesTable.loading ? t('emptyData') : ''
}}</span>
</template>
<el-table-column prop="created_at" label="时间" />
<el-table-column prop="name" label="操作人员" />
<el-table-column prop="type" label="操作类型">
<template #default="scope">
<div v-html="scope.row.type"></div>
</template>
</el-table-column>
<el-table-column prop="values" label="详细信息">
<template #default="scope">
<div v-html="scope.row.values"></div>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="customerResourceChangesTable.page"
v-model:page-size="customerResourceChangesTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="customerResourceChangesTable.total"
@size-change="loadCustomerResourceChangesList()"
@current-change="loadCustomerResourceChangesList"
/>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import {
getLogList,
} from '@/app/api/customer_resources'
import { img } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const props = defineProps({
value: Number
})
let customerResourceChangesTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
customer_resource_id: props.value,
},
})
/**
* 获取客户资源表变更记录列表
*/
const loadCustomerResourceChangesList = (page: number = 1) => {
customerResourceChangesTable.loading = true
customerResourceChangesTable.page = page
getLogList({
page: customerResourceChangesTable.page,
limit: customerResourceChangesTable.limit,
...customerResourceChangesTable.searchParam,
})
.then((res) => {
customerResourceChangesTable.loading = false
customerResourceChangesTable.data = res.data.data
customerResourceChangesTable.total = res.data.total
})
.catch(() => {
customerResourceChangesTable.loading = false
})
}
loadCustomerResourceChangesList()
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

118
admin/src/app/views/customer_resources/components/order_table.vue

@ -0,0 +1,118 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
</div>
<div class="mt-[10px]">
<el-table
:data="customerResourceChangesTable.data"
size="large"
v-loading="customerResourceChangesTable.loading"
>
<template #empty>
<span>{{
!customerResourceChangesTable.loading ? t('emptyData') : ''
}}</span>
</template>
<el-table-column prop="payment_id" label="订单号" />
<el-table-column prop="course_name" label="课程名称" />
<el-table-column prop="order_amount" label="金额" />
<el-table-column prop="order_status" label="状态" />
<el-table-column prop="created_at" label="下单时间" />
<el-table-column prop="type" label="支付方式" />
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="customerResourceChangesTable.page"
v-model:page-size="customerResourceChangesTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="customerResourceChangesTable.total"
@size-change="loadCustomerResourceChangesList()"
@current-change="loadCustomerResourceChangesList"
/>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import {
getOrderTableList,
} from '@/app/api/customer_resources'
import { useRoute } from 'vue-router'
const route = useRoute()
const props = defineProps({
value: Number
})
let customerResourceChangesTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
customer_resource_id: props.value,
},
})
const getProgress = (row) => {
if (!row.total) return 0;
return Math.round((row.used / row.total) * 100);
}
/**
* 获取客户资源表变更记录列表
*/
const loadCustomerResourceChangesList = (page: number = 1) => {
customerResourceChangesTable.loading = true
customerResourceChangesTable.page = page
getOrderTableList({
page: customerResourceChangesTable.page,
limit: customerResourceChangesTable.limit,
...customerResourceChangesTable.searchParam,
})
.then((res) => {
customerResourceChangesTable.loading = false
customerResourceChangesTable.data = res.data.data
customerResourceChangesTable.total = res.data.total
})
.catch(() => {
customerResourceChangesTable.loading = false
})
}
loadCustomerResourceChangesList()
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

131
admin/src/app/views/customer_resources/components/student_courses.vue

@ -0,0 +1,131 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
</div>
<div class="mt-[10px]">
<el-table
:data="customerResourceChangesTable.data"
size="large"
v-loading="customerResourceChangesTable.loading"
>
<template #empty>
<span>{{
!customerResourceChangesTable.loading ? t('emptyData') : ''
}}</span>
</template>
<el-table-column prop="course_name" label="课程名称" />
<el-table-column label="学习进度">
<template #default="{ row }">
<div style="display: flex; align-items: center; justify-content: space-between;">
<el-progress
:percentage="getProgress(row)"
:text-inside="true"
stroke-width="18"
status="success"
style="flex: 1; max-width: 80%;"
/>
<span style="margin-left: 2px; white-space: nowrap; font-size: 14px; color: #666;">
{{ row.used }}/{{ row.total }}
</span>
</div>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" />
<el-table-column prop="start_date" label="开始时间" />
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="customerResourceChangesTable.page"
v-model:page-size="customerResourceChangesTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="customerResourceChangesTable.total"
@size-change="loadCustomerResourceChangesList()"
@current-change="loadCustomerResourceChangesList"
/>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import {
getStudentCoursesList,
} from '@/app/api/customer_resources'
import { useRoute } from 'vue-router'
const route = useRoute()
const props = defineProps({
value: Number
})
let customerResourceChangesTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
customer_resource_id: props.value,
},
})
const getProgress = (row) => {
if (!row.total) return 0;
return Math.round((row.used / row.total) * 100);
}
/**
* 获取客户资源表变更记录列表
*/
const loadCustomerResourceChangesList = (page: number = 1) => {
customerResourceChangesTable.loading = true
customerResourceChangesTable.page = page
getStudentCoursesList({
page: customerResourceChangesTable.page,
limit: customerResourceChangesTable.limit,
...customerResourceChangesTable.searchParam,
})
.then((res) => {
customerResourceChangesTable.loading = false
customerResourceChangesTable.data = res.data.data
customerResourceChangesTable.total = res.data.total
})
.catch(() => {
customerResourceChangesTable.loading = false
})
}
loadCustomerResourceChangesList()
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

15
admin/src/app/views/customer_resources/customer_resources.vue

@ -127,6 +127,9 @@
<el-dropdown-item command="resourceChanges"> <el-dropdown-item command="resourceChanges">
客户信息修改记录 客户信息修改记录
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item command="UserProfile">
客户详情
</el-dropdown-item>
<el-dropdown-item command="editEvent"> <el-dropdown-item command="editEvent">
{{ t('edit') }} {{ t('edit') }}
</el-dropdown-item> </el-dropdown-item>
@ -180,6 +183,7 @@
<tc ref="TcCustomerResourcesDialog" @complete="loadCustomerResourcesList" /> <tc ref="TcCustomerResourcesDialog" @complete="loadCustomerResourcesList" />
<user ref="UserProfileDialog" @complete="loadCustomerResourcesList" />
</el-card> </el-card>
</div> </div>
</template> </template>
@ -195,6 +199,8 @@
import Fp from '@/app/views/customer_resources/components/fp.vue' import Fp from '@/app/views/customer_resources/components/fp.vue'
import Order from '@/app/views/order_table/components/order-table-edit.vue' import Order from '@/app/views/order_table/components/order-table-edit.vue'
import Tc from '@/app/views/tc_dialog/tc_dialog.vue' import Tc from '@/app/views/tc_dialog/tc_dialog.vue'
import User from '@/app/views/customer_resources/components/UserProfile.vue'
import { ArrowDown } from '@element-plus/icons-vue' import { ArrowDown } from '@element-plus/icons-vue'
import { getMemberLabelAll } from '@/app/api/member' import { getMemberLabelAll } from '@/app/api/member'
@ -244,6 +250,9 @@
case 'deleteEvent': case 'deleteEvent':
deleteEvent(row.id) deleteEvent(row.id)
break break
case 'UserProfile':
UserProfile(row)
break
} }
} }
@ -278,6 +287,7 @@
} }
const TcCustomerResourcesDialog : Record<string, any> | null = ref(null) const TcCustomerResourcesDialog : Record<string, any> | null = ref(null)
const tcEvent = (row : any) => { const tcEvent = (row : any) => {
TcCustomerResourcesDialog.value.setFormData(row) TcCustomerResourcesDialog.value.setFormData(row)
@ -290,7 +300,12 @@
} }
const UserProfileDialog : Record<string, any> | null = ref(null)
const UserProfile = (row : any) => {
UserProfileDialog.value.setFormData(row)
UserProfileDialog.value.showDialog = true
}
const searchFormRef = ref<FormInstance>() const searchFormRef = ref<FormInstance>()

14
admin/src/app/views/school_approval/process/index.vue

@ -52,9 +52,9 @@
> >
<el-table-column :label="'ID'" prop="id" width="80" /> <el-table-column :label="'ID'" prop="id" width="80" />
<el-table-column :label="'流程名称'" prop="process_name" min-width="180" /> <el-table-column :label="'流程名称'" prop="process_name" min-width="180" />
<el-table-column :label="'申请人ID'" prop="applicant_id" width="100" /> <el-table-column :label="'申请人'" prop="applicant_name" width="100" />
<el-table-column :label="'申请时间'" prop="application_time" width="180" /> <el-table-column :label="'申请时间'" prop="application_time" width="180" />
<el-table-column :label="'当前审批人ID'" prop="current_approver_id" width="100" /> <el-table-column :label="'当前审批人'" prop="current_approver_name" width="100" />
<el-table-column :label="'审批状态'" prop="approval_status" width="100"> <el-table-column :label="'审批状态'" prop="approval_status" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="getStatusType(row.approval_status)"> <el-tag :type="getStatusType(row.approval_status)">
@ -202,14 +202,14 @@
<el-descriptions-item :label="'流程名称'"> <el-descriptions-item :label="'流程名称'">
{{ state.detailDialog.info.process_name }} {{ state.detailDialog.info.process_name }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item :label="'申请人ID'"> <el-descriptions-item :label="'申请人'">
{{ state.detailDialog.info.applicant_id }} {{ state.detailDialog.info.applicant_name }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item :label="'申请时间'"> <el-descriptions-item :label="'申请时间'">
{{ state.detailDialog.info.application_time }} {{ state.detailDialog.info.application_time }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item :label="'当前审批人ID'"> <el-descriptions-item :label="'当前审批人'">
{{ state.detailDialog.info.current_approver_id }} {{ state.detailDialog.info.current_approver_name }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item :label="'审批状态'"> <el-descriptions-item :label="'审批状态'">
<el-tag :type="getStatusType(state.detailDialog.info.approval_status)"> <el-tag :type="getStatusType(state.detailDialog.info.approval_status)">
@ -237,7 +237,7 @@
{{ '参与者' + (index + 1) }} {{ '参与者' + (index + 1) }}
</div> </div>
<div class="text-gray-500"> <div class="text-gray-500">
{{ '参与者ID' }}{{ node.participant_id }} {{ '参与者' }}{{ node.name }}
</div> </div>
<div class="text-gray-500"> <div class="text-gray-500">
{{ '顺序' }}{{ node.sequence }} {{ '顺序' }}{{ node.sequence }}

165
admin/src/app/views/service_logs/service_logs.vue

@ -0,0 +1,165 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-lg">{{ pageName }}</span>
</div>
<el-card
class="box-card !border-none my-[10px] table-search-wrap"
shadow="never"
>
<el-form
:inline="true"
:model="studentCourseUsageTable.searchParam"
ref="searchFormRef"
>
<el-form-item label="家长姓名" prop="name">
<el-input
v-model="studentCourseUsageTable.searchParam.name"
placeholder="请输入家长姓名"
/>
</el-form-item>
<el-form-item label="评分" prop="score">
<el-input
v-model="studentCourseUsageTable.searchParam.score"
placeholder="请输入评分"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadServiceLogsList()">{{
t('search')
}}</el-button>
<el-button @click="resetForm(searchFormRef)">{{
t('reset')
}}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table
:data="studentCourseUsageTable.data"
size="large"
v-loading="studentCourseUsageTable.loading"
>
<template #empty>
<span>{{
!studentCourseUsageTable.loading ? t('emptyData') : ''
}}</span>
</template>
<el-table-column prop="name" label="家长姓名" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="staff_name" label="教练姓名" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="service_name" label="服务内容" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="customer_confirmation" label="是否需要反馈" min-width="120" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-if="row.customer_confirmation == 1"></div>
<div v-if="row.customer_confirmation == 0"></div>
</template>
</el-table-column>
<el-table-column prop="score" label="反馈分数" min-width="120" :show-overflow-tooltip="true"/>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="studentCourseUsageTable.page"
v-model:page-size="studentCourseUsageTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="studentCourseUsageTable.total"
@size-change="loadServiceLogsList()"
@current-change="loadServiceLogsList"
/>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import {
getServiceLogsList,
} from '@/app/api/service_logs'
import { img } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
let studentCourseUsageTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
name: '',
score: '',
},
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
/**
* 获取学员课时消费记录列表
*/
const loadServiceLogsList = (page: number = 1) => {
studentCourseUsageTable.loading = true
studentCourseUsageTable.page = page
getServiceLogsList({
page: studentCourseUsageTable.page,
limit: studentCourseUsageTable.limit,
...studentCourseUsageTable.searchParam,
})
.then((res) => {
studentCourseUsageTable.loading = false
studentCourseUsageTable.data = res.data.data
studentCourseUsageTable.total = res.data.total
})
.catch(() => {
studentCourseUsageTable.loading = false
})
}
loadServiceLogsList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

88
admin/src/app/views/student_course_usage/student_course_usage.vue

@ -3,9 +3,6 @@
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<span class="text-lg">{{ pageName }}</span> <span class="text-lg">{{ pageName }}</span>
<el-button type="primary" @click="addEvent">
{{ t('addStudentCourseUsage') }}
</el-button>
</div> </div>
<el-card <el-card
@ -17,25 +14,28 @@
:model="studentCourseUsageTable.searchParam" :model="studentCourseUsageTable.searchParam"
ref="searchFormRef" ref="searchFormRef"
> >
<el-form-item :label="t('studentCourseId')" prop="student_course_id"> <el-form-item label="家长名称" prop="emergency_contact">
<el-input <el-input
v-model="studentCourseUsageTable.searchParam.student_course_id" v-model="studentCourseUsageTable.searchParam.emergency_contact"
:placeholder="t('studentCourseIdPlaceholder')" placeholder="请输入家长名称"
/>
</el-form-item>
<el-form-item :label="t('usedHours')" prop="used_hours">
<el-input
v-model="studentCourseUsageTable.searchParam.used_hours"
:placeholder="t('usedHoursPlaceholder')"
/>
</el-form-item>
<el-form-item :label="t('usageDate')" prop="usage_date">
<el-input
v-model="studentCourseUsageTable.searchParam.usage_date"
:placeholder="t('usageDatePlaceholder')"
/> />
</el-form-item> </el-form-item>
<el-form-item label="学生名称" prop="student_name">
<el-input
v-model="studentCourseUsageTable.searchParam.student_name"
placeholder="请输入学生名称"
/>
</el-form-item>
<el-form-item label="手机号" prop="contact_phone">
<el-input
v-model="studentCourseUsageTable.searchParam.contact_phone"
placeholder="请输入手机号"
/>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="loadStudentCourseUsageList()">{{ <el-button type="primary" @click="loadStudentCourseUsageList()">{{
t('search') t('search')
@ -58,41 +58,23 @@
!studentCourseUsageTable.loading ? t('emptyData') : '' !studentCourseUsageTable.loading ? t('emptyData') : ''
}}</span> }}</span>
</template> </template>
<el-table-column
prop="student_course_id"
:label="t('studentCourseId')"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column <el-table-column prop="course_name" label="课程名称" min-width="120" :show-overflow-tooltip="true"/>
prop="used_hours"
:label="t('usedHours')" <el-table-column prop="student_name" label="学员姓名" min-width="120" :show-overflow-tooltip="true"/>
min-width="120"
:show-overflow-tooltip="true" <el-table-column prop="emergency_contact" label="家长称呼" min-width="120" :show-overflow-tooltip="true"/>
/>
<el-table-column prop="total_hours" label="课时数量" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="used_hours" label="消课数量" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="sy_time" label="剩余课时" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="gift_hours" label="赠送课时" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column
prop="usage_date"
:label="t('usageDate')"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column
:label="t('operation')"
fixed="right"
min-width="120"
>
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{
t('edit')
}}</el-button>
<el-button type="primary" link @click="deleteEvent(row.id)">{{
t('delete')
}}</el-button>
</template>
</el-table-column>
</el-table> </el-table>
<div class="mt-[16px] flex justify-end"> <div class="mt-[16px] flex justify-end">
<el-pagination <el-pagination
@ -136,9 +118,9 @@ let studentCourseUsageTable = reactive({
loading: true, loading: true,
data: [], data: [],
searchParam: { searchParam: {
student_course_id: '', emergency_contact: '',
used_hours: '', student_name: '',
usage_date: '', contact_phone: '',
}, },
}) })

29
niucloud/app/adminapi/controller/customer_resources/CustomerResources.php

@ -41,6 +41,8 @@ class CustomerResources extends BaseAdminController
return success((new CustomerResourcesService())->getPage($data)); return success((new CustomerResourcesService())->getPage($data));
} }
/** /**
* 客户资源详情 * 客户资源详情
* @param int $id * @param int $id
@ -196,4 +198,31 @@ class CustomerResources extends BaseAdminController
{ {
return success((new CustomerResourcesService())->getResourceByCourse($schedule)); return success((new CustomerResourcesService())->getResourceByCourse($schedule));
} }
public function log_list()
{
$data = $this->request->params([
["customer_resource_id", ""]
]);
return success((new CustomerResourcesService())->log_list($data));
}
public function student_courses()
{
$data = $this->request->params([
["customer_resource_id", ""]
]);
return success((new CustomerResourcesService())->student_courses($data));
}
public function order_table()
{
$data = $this->request->params([
["customer_resource_id", ""]
]);
return success((new CustomerResourcesService())->order_table($data));
}
} }

10
niucloud/app/adminapi/controller/school_approval/Process.php

@ -37,25 +37,25 @@ class Process extends BaseAdminController
$where = []; $where = [];
if ($status !== '') { if ($status !== '') {
$where[] = ['approval_status', '=', $status]; $where[] = ['a.approval_status', '=', $status];
} }
$process_name = input('process_name', ''); $process_name = input('process_name', '');
if (!empty($process_name)) { if (!empty($process_name)) {
$where[] = ['process_name', 'like', "%{$process_name}%"]; $where[] = ['a.process_name', 'like', "%{$process_name}%"];
} }
// 我发起的审批 // 我发起的审批
$applicant_id = input('applicant_id', 0); $applicant_id = input('applicant_id', 0);
if (!empty($applicant_id)) { if (!empty($applicant_id)) {
$where[] = ['applicant_id', '=', $applicant_id]; $where[] = ['a.applicant_id', '=', $applicant_id];
} }
// 待我审批的 // 待我审批的
$approver_id = input('approver_id', 0); $approver_id = input('approver_id', 0);
if (!empty($approver_id)) { if (!empty($approver_id)) {
$where[] = ['current_approver_id', '=', $approver_id]; $where[] = ['a.current_approver_id', '=', $approver_id];
$where[] = ['approval_status', '=', 'pending']; $where[] = ['a.approval_status', '=', 'pending'];
} }
$data = $this->service->getList($where, (int)$page, (int)$limit); $data = $this->service->getList($where, (int)$page, (int)$limit);

39
niucloud/app/adminapi/controller/service_logs/ServiceLogs.php

@ -0,0 +1,39 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\adminapi\controller\service_logs;
use app\service\admin\service_logs\ServiceLogsService;
use core\base\BaseAdminController;
use app\service\admin\service\ServiceService;
/**
* 服务控制器
* Class Service
* @package app\adminapi\controller\service
*/
class ServiceLogs extends BaseAdminController
{
/**
* 获取服务列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
["name",""],
["score",""]
]);
return success((new ServiceLogsService())->getPage($data));
}
}

6
niucloud/app/adminapi/controller/student_course_usage/StudentCourseUsage.php

@ -28,9 +28,9 @@ class StudentCourseUsage extends BaseAdminController
*/ */
public function lists(){ public function lists(){
$data = $this->request->params([ $data = $this->request->params([
["student_course_id",""], ["emergency_contact",""],
["used_hours",""], ["student_name",""],
["usage_date",""] ["contact_phone",""]
]); ]);
return success((new StudentCourseUsageService())->getPage($data)); return success((new StudentCourseUsageService())->getPage($data));
} }

5
niucloud/app/adminapi/route/customer_resources.php

@ -47,6 +47,11 @@ Route::group('customer_resources', function () {
Route::get('getResourceByCourse/:schedule/students', 'customer_resources.CustomerResources/getResourceByCourse'); Route::get('getResourceByCourse/:schedule/students', 'customer_resources.CustomerResources/getResourceByCourse');
Route::get('log_list','customer_resources.CustomerResources/log_list');
Route::get('student_courses','customer_resources.CustomerResources/student_courses');
Route::get('order_table','customer_resources.CustomerResources/order_table');
})->middleware([ })->middleware([
AdminCheckToken::class, AdminCheckToken::class,
AdminCheckRole::class, AdminCheckRole::class,

31
niucloud/app/adminapi/route/service_logs.php

@ -0,0 +1,31 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
use think\facade\Route;
use app\adminapi\middleware\AdminCheckRole;
use app\adminapi\middleware\AdminCheckToken;
use app\adminapi\middleware\AdminLog;
// USER_CODE_BEGIN -- service
Route::group('service_logs', function () {
Route::get('service_logs', 'service_logs.ServiceLogs/lists');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_END -- service

88
niucloud/app/api/controller/apiController/ClassApi.php

@ -12,7 +12,8 @@
namespace app\api\controller\apiController; namespace app\api\controller\apiController;
use app\Request; use app\Request;
use app\service\api\apiService\CourseService; use app\service\api\apiService\jlClassService;
use app\service\api\apiService\PhysicalTestService;
use core\base\BaseApiService; use core\base\BaseApiService;
@ -21,22 +22,93 @@ use core\base\BaseApiService;
* Class Personnel * Class Personnel
* @package app\api\controller\apiController * @package app\api\controller\apiController
*/ */
class ClassSpi extends BaseApiService class ClassApi extends BaseApiService
{ {
//课程列表 //课程列表
public function jlClassList(Request $request){ public function jlClassList(Request $request){
$id = $this->member_id; $id = $this->member_id;
dd(111); $data = $this->request->params([
return success((new CourseService())->list($id,$data)); ["name",'']
]);
return success((new jlClassService())->list($id,$data));
}
//课程详情
public function jlClassInfo(Request $request){
$data = $this->request->params([
["class_id",0]
]);
return success('获取成功',(new jlClassService())->info($data['class_id']));
} }
//获取课程详情 //获取学员详情
public function courseInfo(Request $request){ public function jlStudentsInfo(Request $request){
$data = $this->request->params([ $data = $this->request->params([
["id",0] ["students_id",0]
]); ]);
return success('SUCCESS',(new CourseService())->info($data['id'])); return success('获取成功',(new jlClassService())->jlStudentsInfo($data['students_id']));
}
//体测列表
public function PhysicalTestList(Request $request){
$data = $this->request->params([
["user_id",0]
]);
return success('获取成功',(new jlClassService())->PhysicalTestList($data['user_id']));
}
//体测详情
public function PhysicalTestInfo(Request $request)
{
$id = $request->param('survey_id', '');//体测报告的id
if (empty($id)) {
return fail('缺少参数');
}
$where = [
'id' => $id,
];
$res = (new PhysicalTestService())->getInfo($where);
if(!$res['code']){
return fail($res['msg']);
}
return success($res['data']);
} }
//添加作业-获取班级列表
public function jlGetClassesList(Request $request)
{
return success((new jlClassService())->GetClassesList());
}
//添加作业-获取课程列表
public function jlGetCoursesList(Request $request)
{
return success((new jlClassService())->GetCoursesList());
}
//添加作业-学员列表
public function jlGetStudentList(Request $request)
{
return success((new jlClassService())->GetStudentList());
}
//添加作业
public function addJlPublishJob(Request $request)
{
$data = $this->request->params([
["class_id",0],
["classes_id_name",''],
["content_text",''],
["content_type",''],
["course_id",0],
["course_id_name",''],
["student_id",''],
["students_ids_name",''],
["type",''],
]);
return success('操作成功', (new jlClassService())->addPublishJob($data));
}
} }

6
niucloud/app/api/controller/apiController/Course.php

@ -33,6 +33,12 @@ class Course extends BaseApiService
return success((new CourseService())->list($id,$data)); return success((new CourseService())->list($id,$data));
} }
//班级课程列表
public function classCourseList(Request $request){
$id = $this->member_id;
return success((new CourseService())->classList($id));
}
//获取课程详情 //获取课程详情
public function courseInfo(Request $request){ public function courseInfo(Request $request){
$data = $this->request->params([ $data = $this->request->params([

119
niucloud/app/api/controller/apiController/CustomerResourcesAuth.php

@ -0,0 +1,119 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\api\controller\apiController;
use app\dict\member\MemberLoginTypeDict;
use app\model\member\Member;
use app\Request;
use app\service\api\apiService\CustomerResourcesService;
use app\service\api\login\LoginService;
use core\base\BaseApiService;
/**
* 学员登陆控制器相关接口
* Class Personnel
* @package app\api\controller\apiController
*/
class customerResourcesAuth extends BaseApiService
{
//获取字典
public function login(Request $request)
{
$phone = $request->param('phone', ''); //手机号
$password = $request->param('password', ''); //密码
$openid = $request->param('openid', ''); //微信小程序openid
if (empty($phone)) {
return fail('请输入手机号');
}
if (empty($password)) {
return fail('请输入密码');
}
$member_info = Member::where('mobile', $phone)->find();//查账户表信息是否存在
if (!$member_info) {
return fail('账户手机号有误');
}
$customerResources = \app\model\customer_resources\CustomerResources::where('member_id', $member_info['member_id'])->find();//查客户资源表信息是否存在
if (!$customerResources) {
return fail('账户信息有误');
}
//创建密码
//$a = create_password($password);
//验证密码
if (!check_password($password, $member_info->password)) {
return fail('手机号或密码不正确');
}
$res = (new LoginService())->login($member_info, MemberLoginTypeDict::MOBILE);
if (!$res) {
return fail('账户信息有误');
}
$res['user_type'] = '3';//用户类型|3=学员
return success($res);
}
//学生详情
public function info(){
$member_id = $this->member_id;
$where = [
'member_id'=>$member_id
];
$res = (new CustomerResourcesService())->getInfo($where);
if (!$res['code']) {
return fail($res['msg']);
}
return success($res['data']);
}
//学生详情-修改
public function edit(Request $request){
$member_id = $this->member_id;
$where = [
'member_id'=>$member_id
];
$data = [
'headimg' => $request->param('headimg', ''),
'name' => $request->param('name', ''),
'gender' => $request->param('gender', ''),
'age' => $request->param('age', ''),
'phone_number' => $request->param('phone_number', ''),
];
// 验证必填字段
if (empty($data['name'])) {
return fail('姓名不能为空');
}
if (empty($data['gender'])) {
return fail('性别不能为空');
}
if (empty($data['age'])) {
return fail('年龄不能为空');
}
if (empty($data['phone_number'])) {
return fail('手机号不能为空');
}
$res = (new CustomerResourcesService())->editInfo($where,$data);
if (!$res['code']) {
return fail($res['msg']);
}
return success([]);
}
}

42
niucloud/app/api/controller/apiController/PersonCourseSchedule.php

@ -0,0 +1,42 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\api\controller\apiController;
use app\Request;
use app\service\api\apiService\PersonCourseScheduleService;
use core\base\BaseApiService;
/**
* 学生课程安排-控制器相关接口
* Class Personnel
* @package app\api\controller\apiController
*/
class PersonCourseSchedule extends BaseApiService
{
//列表
public function index(Request $request)
{
$resources_id = $request->param('resources_id', '');//客户资源ID
if (empty($resources_id)) {
return fail('缺少参数');
}
$where = [
'resources_id' => $resources_id,
];
$res = (new PersonCourseScheduleService())->getList($where);
return success($res);
}
}

65
niucloud/app/api/controller/apiController/PhysicalTest.php

@ -0,0 +1,65 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\api\controller\apiController;
use app\Request;
use app\service\api\apiService\ChatService;
use app\service\api\apiService\PhysicalTestService;
use core\base\BaseApiService;
/**
* 体测报告-控制器相关接口
* Class Personnel
* @package app\api\controller\apiController
*/
class PhysicalTest extends BaseApiService
{
//列表
public function index(Request $request)
{
$resource_id = $request->param('resource_id', '');//学生资源表id
if (empty($resource_id)) {
return fail('缺少参数');
}
$where = [
'resource_id' => $resource_id,
];
$res = (new PhysicalTestService())->getList($where);
return success($res);
}
//详情
public function info(Request $request)
{
$id = $request->param('id', '');//体测报告的id
if (empty($id)) {
return fail('缺少参数');
}
$where = [
'id' => $id,
];
$res = (new PhysicalTestService())->getInfo($where);
if(!$res['code']){
return fail($res['msg']);
}
return success($res['data']);
}
}

7
niucloud/app/api/controller/apiController/TeachingResearch.php

@ -115,10 +115,15 @@ class TeachingResearch extends BaseApiService
if ($resLessonTeaching['answers_num'] >= $res['number_answers']) { if ($resLessonTeaching['answers_num'] >= $res['number_answers']) {
return fail('已超过答题次数', []); return fail('已超过答题次数', []);
} else { } else {
if (count($userRes['data']['cameus_dept_arr']) > 0) {
$campus_id = $userRes['data']['cameus_dept_arr'][0]['campus_id'];
} else {
$campus_id = 0;
}
foreach ($result as &$v){ foreach ($result as &$v){
$v['user_id'] = $userRes['data']['id']; $v['user_id'] = $userRes['data']['id'];
$v['question_id'] = $v['ids']; $v['question_id'] = $v['ids'];
$v['campus_id'] = 0; $v['campus_id'] = $campus_id;
$v['answer'] = $v['value']; $v['answer'] = $v['value'];
$resEq = $ExamQuestions->where('id',$v['ids'])->find(); $resEq = $ExamQuestions->where('id',$v['ids'])->find();
if ($resEq['correct_answer'] == $v['value']){ if ($resEq['correct_answer'] == $v['value']){

46
niucloud/app/api/controller/apiController/Test.php

@ -0,0 +1,46 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\api\controller\apiController;
use app\Request;
use app\service\api\apiService\CampusService;
use app\service\api\apiService\ChatService;
use app\service\api\apiService\CommonService;
use core\base\BaseApiService;
/**
* 测试控制器相关接口
* Class Personnel
* @package app\api\controller\apiController
*/
class Test extends BaseApiService
{
//测试控制器Demo
public function index(Request $request)
{
$personnel_id = $request->param('personnel_id', '');//员工人力资源表id(两个参数2选1)
$customer_resources_id = $request->param('customer_resources_id', '');//学生资源表id(两个参数2选1)
if (empty($personnel_id) && empty($customer_resources_id)) {
return fail('缺少参数');
}
$where = [
'personnel_id' => $personnel_id,
'customer_resources_id' => $customer_resources_id,
];
$res = (new ChatService())->getChatFriendsPage($where);
return success($res);
}
}

53
niucloud/app/api/controller/apiController/UserFeedback.php

@ -0,0 +1,53 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\api\controller\apiController;
use app\Request;
use core\base\BaseApiService;
/**
* 学生用户反馈控制器相关接口
* Class Personnel
* @package app\api\controller\apiController
*/
class UserFeedback extends BaseApiService
{
//学生用户反馈-添加
public function add(Request $request)
{
// 接受参数
$user_id = $request->post('user_id', ''); // 用户ID(对应school_customer_resources表id)
$feedback_text = $request->post('feedback_text', ''); // 反馈内容
$attachment_url = $request->post('attachment_url', null); // 附件URL(OSS对象存储),允许为空
//验证必填
if (empty($user_id) || empty($feedback_text)) {
return fail('必填参数不能为空');
}
$data = [
'user_id' => $user_id,
'feedback_text' => $feedback_text,
'attachment_url' => $attachment_url ?? null,
];
$add = \app\model\user_feedback\UserFeedback::create($data);
if (!$add) {
return fail('添加失败');
}
return success([]);
}
}

12
niucloud/app/api/controller/upload/Upload.php

@ -33,7 +33,17 @@ class Upload extends BaseApiController
['file', 'file'], ['file', 'file'],
]); ]);
$upload_service = new UploadService(); $upload_service = new UploadService();
return success($upload_service->image($data['file'],$extraData));
$res = $upload_service->image($data['file'],$extraData);
$res['ext'] = ''; // 初始化文件扩展名
$res['name'] = ''; // 初始化文件名称
if (isset($res['url'])) {
$res['ext'] = pathinfo($res['url'], PATHINFO_EXTENSION);
$res['name'] = basename($res['url']);
}
return success($res);
} }
/** /**

67
niucloud/app/api/route/route.php

@ -278,22 +278,30 @@ Route::group(function () {
//添加作业
Route::get('class/jlPublishJob/add', 'apiController.classApi/addJlPublishJob');
//添加作业-获取课程列表
Route::get('class/jlGetStudentList/list', 'apiController.classApi/jlGetStudentList');
//添加作业-获取课程列表
Route::get('class/jlGetCoursesList/list', 'apiController.classApi/jlGetCoursesList');
//添加作业-获取班级列表
Route::get('class/jlGetClasses/list', 'apiController.classApi/jlGetClassesList');
//体测报告-列表
Route::get('class/physicalTest', 'apiController.classApi/PhysicalTestList');
//体测报告-详情
Route::get('class/physicalTest/info', 'apiController.classApi/PhysicalTestInfo');
//获取学员详情
Route::get('class/jlStudentsInfo', 'apiController.classApi/jlStudentsInfo');
//班级课程列表
Route::get('course/classCourseList', 'apiController.course/classCourseList');
//获取添加学员列表 //获取添加学员列表
Route::get('course/addStudentList', 'apiController.course/addStudentList'); Route::get('course/addStudentList', 'apiController.course/addStudentList');
Route::post('course/addStudent', 'apiController.course/addStudent'); Route::post('course/addStudent', 'apiController.course/addStudent');
Route::get('course/delStudentCourse', 'apiController.course/delStudentCourse'); Route::get('course/delStudentCourse', 'apiController.course/delStudentCourse');
//班级列表 //班级列表
Route::get('class/jlClassList', 'apiController.classApi/jlClassList'); Route::get('class/jlClassList', 'apiController.classApi/jlClassList');
//班级详情
Route::get('class/jlClassInfo', 'apiController.classApi/jlClassInfo');
//课程列表 //课程列表
Route::get('course/courseList', 'apiController.course/courseList'); Route::get('course/courseList', 'apiController.course/courseList');
//获取课程详情 //获取课程详情
@ -314,10 +322,11 @@ Route::group(function () {
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑-----员工端相关-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑-----员工端相关-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓-----用户端相关-----↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓-----学生用户端相关-----↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//无需token验证的 //无需token验证的
Route::group(function () { Route::group(function () {
// Route::post('personnelLogin', 'login.Login/personnelLogin'); //学生登录
Route::post('customerResourcesAuth/login', 'apiController.CustomerResourcesAuth/login');
})->middleware(ApiChannel::class) })->middleware(ApiChannel::class)
->middleware(ApiCheckToken::class) ->middleware(ApiCheckToken::class)
->middleware(ApiLog::class); ->middleware(ApiLog::class);
@ -325,12 +334,42 @@ Route::group(function () {
//需要token验证的 //需要token验证的
Route::group(function () { Route::group(function () {
// Route::get('personnel/info', 'apiController.Personnel/info'); //员工端-上传图片
Route::post('memberUploadImage', 'upload.Upload/image');
//学生详情
Route::get('customerResourcesAuth/info', 'apiController.CustomerResourcesAuth/info');
//学生详情-修改
Route::post('customerResourcesAuth/edit', 'apiController.CustomerResourcesAuth/edit');
//学生用户反馈-添加
Route::post('userFeedback/add', 'apiController.UserFeedback/add');
//学生端-用户聊天-好友关系列表
Route::get('xy/chat/getChatFriendsList', 'apiController.Chat/getChatFriendsList');
//学生端-用户聊天-好友关系详情
Route::get('xy/chat/getChatFriendsInfo', 'apiController.Chat/getChatFriendsInfo');
//学生端-用户聊天-获取聊天记录
Route::get('xy/chat/getChatMessagesList', 'apiController.Chat/getChatMessagesList');
//学生端-用户聊天-发送聊天内容
Route::post('xy/chat/sendChatMessages', 'apiController.Chat/sendChatMessages');
//学生端-体测报告-列表
Route::get('xy/physicalTest', 'apiController.PhysicalTest/index');
//学生端-体测报告-详情
Route::get('xy/physicalTest/info', 'apiController.PhysicalTest/info');
//学生端-学生课程安排-列表
Route::get('xy/personCourseSchedule', 'apiController.PersonCourseSchedule/index');
//学生端-学生课程安排-详情
Route::get('xy/personCourseSchedule/info', 'apiController.PersonCourseSchedule/info');
})->middleware(ApiChannel::class) })->middleware(ApiChannel::class)
->middleware(ApiCheckToken::class, true) ->middleware(ApiCheckToken::class, true)
->middleware(ApiLog::class); ->middleware(ApiLog::class);
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑-----用户端相关-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑-----学生用户端相关-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
//加载插件路由 //加载插件路由

19
niucloud/app/common.php

@ -1214,3 +1214,22 @@ function calculateChildHealthScore($age, $gender, $height, $weight) {
// 四舍五入取整 // 四舍五入取整
return round($total_score); return round($total_score);
} }
function get_dict_value($key,$value){
$dict = new \app\model\dict\Dict();
$field = 'id,name,key,dictionary,memo,create_time,update_time';
$info = $dict->field($field)->where([['key', '=', $key]])->findOrEmpty()->toArray();
if($info['dictionary'] == null)
{
$info['dictionary'] = [];
}
$map = [];
foreach ($info['dictionary'] as $item) {
$map[$item['value']] = $item['name'];
}
return $map[$value];
}

11
niucloud/app/model/class_grade/ClassGrade.php

@ -13,6 +13,7 @@ namespace app\model\class_grade;
use app\model\campus\Campus; use app\model\campus\Campus;
use app\model\personnel\Personnel; use app\model\personnel\Personnel;
use app\model\class_personnel_rel\ClassPersonnelRel;
use core\base\BaseModel; use core\base\BaseModel;
use think\model\concern\SoftDelete; use think\model\concern\SoftDelete;
use think\model\relation\HasMany; use think\model\relation\HasMany;
@ -229,6 +230,16 @@ class ClassGrade extends BaseModel
return $this->hasOne(Personnel::class, 'id', 'head_coach')->joinType('left')->withField('name,id')->bind(['head_coach_name'=>'name']); return $this->hasOne(Personnel::class, 'id', 'head_coach')->joinType('left')->withField('name,id')->bind(['head_coach_name'=>'name']);
} }
public function personnelAll(){
return $this->hasOne(Personnel::class, 'id', 'head_coach')->joinType('left')->withField('head_img,id')->bind(['head_coach_head_img'=>'head_img']);
}
public function personnelName(){
return $this->hasOne(Personnel::class, 'id', 'head_coach')->joinType('left')->withField('name,id')->bind(['head_coach_name'=>'name']);
}
public function classPersonnelRel(){
return $this->hasMany(ClassPersonnelRel::class, 'class_id', 'id');
}
} }

57
niucloud/app/model/class_personnel_rel/ClassPersonnelRel.php

@ -0,0 +1,57 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\model\class_personnel_rel;
use core\base\BaseModel;
use think\model\concern\SoftDelete;
use think\model\relation\HasMany;
use think\model\relation\HasOne;
use app\model\student\Student;
use app\model\student_courses\StudentCourses;
use app\model\class_grade\ClassGrade;
use app\model\customer_resources\CustomerResources;
use app\model\campus\Campus;
class ClassPersonnelRel extends BaseModel
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'class_personnel_rel';
public function student(){
return $this->hasOne(Student::class, 'id', 'source_id');
}
public function studentCourses(){
return $this->hasOne(StudentCourses::class, 'student_id', 'source_id')->joinType('left')->withField('end_date,student_id')->bind(['end_date'=>'end_date']);
}
public function studentCoursesInfo(){
return $this->hasOne(StudentCourses::class, 'student_id', 'source_id');
}
}

6
niucloud/app/model/course/Course.php

@ -12,6 +12,7 @@
namespace app\model\course; namespace app\model\course;
use core\base\BaseModel; use core\base\BaseModel;
use app\model\student_courses\StudentCourses;
use think\model\concern\SoftDelete; use think\model\concern\SoftDelete;
use think\model\relation\HasMany; use think\model\relation\HasMany;
use think\model\relation\HasOne; use think\model\relation\HasOne;
@ -171,7 +172,10 @@ class Course extends BaseModel
} }
public function studentCourses()
{
return $this->hasOne(StudentCourses::class, 'course_id', 'id');
}

12
niucloud/app/model/course_schedule/CourseSchedule.php

@ -14,6 +14,8 @@ namespace app\model\course_schedule;
use app\model\course\Course; use app\model\course\Course;
use app\model\personnel\Personnel; use app\model\personnel\Personnel;
use app\model\venue\Venue; use app\model\venue\Venue;
use app\model\campus\Campus;
use app\model\student_courses\StudentCourses;
use core\base\BaseModel; use core\base\BaseModel;
use think\model\concern\SoftDelete; use think\model\concern\SoftDelete;
use think\model\relation\HasMany; use think\model\relation\HasMany;
@ -102,4 +104,14 @@ class CourseSchedule extends BaseModel
return $this->hasOne(Course::class, 'id', 'course_id'); return $this->hasOne(Course::class, 'id', 'course_id');
} }
public function campus()
{
return $this->hasOne(Campus::class, 'id', 'campus_id')->joinType('left')->withField('campus_name,id')->bind(['campus_name'=>'campus_name']);
}
public function studentCourses()
{
return $this->hasOne(StudentCourses::class, 'course_id', 'course_id');
}
} }

7
niucloud/app/model/customer_resources/CustomerResources.php

@ -89,6 +89,7 @@ class CustomerResources extends BaseModel
'updated_at' => '更新时间', 'updated_at' => '更新时间',
'deleted_at' => '逻辑删除时间', 'deleted_at' => '逻辑删除时间',
'status' => '客户状态', 'status' => '客户状态',
'member_label' => '资源标签'
]; ];
public function orderTable() public function orderTable()
@ -162,6 +163,12 @@ class CustomerResources extends BaseModel
return $this->hasMany(ResourceSharing::class, 'resource_id', 'id'); return $this->hasMany(ResourceSharing::class, 'resource_id', 'id');
} }
//一对一关联"用户账号登陆表"
public function memberHasOne()
{
return $this->hasOne(Member::class, 'member_id', 'member_id');
}

7
niucloud/app/model/physical_test/PhysicalTest.php

@ -81,6 +81,13 @@ class PhysicalTest extends BaseModel
return $this->hasOne(CustomerResources::class, 'id', 'resource_id')->joinType('left')->withField('name,id')->bind(['resource_id_name'=>'name']); return $this->hasOne(CustomerResources::class, 'id', 'resource_id')->joinType('left')->withField('name,id')->bind(['resource_id_name'=>'name']);
} }
//获取学生资源一对一
public function customerResourcesHasOne(){
return $this->hasOne(CustomerResources::class, 'id', 'resource_id');
}
public function student(){ public function student(){
return $this->hasOne(Student::class, 'id', 'student_id')->joinType('left')->withField('name,id')->bind(['student_id_name'=>'name']); return $this->hasOne(Student::class, 'id', 'student_id')->joinType('left')->withField('name,id')->bind(['student_id_name'=>'name']);
} }

44
niucloud/app/model/service_logs/ServiceLogs.php

@ -0,0 +1,44 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\model\service_logs;
use core\base\BaseModel;
use think\model\concern\SoftDelete;
use think\model\relation\HasMany;
use think\model\relation\HasOne;
/**
* 服务模型
* Class Service
* @package app\model\service
*/
class ServiceLogs extends BaseModel
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'service_logs';
}

1
niucloud/app/model/student/Student.php

@ -152,4 +152,5 @@ class Student extends BaseModel
return $this->hasOne(ClassGrade::class, 'id', 'class_id'); return $this->hasOne(ClassGrade::class, 'id', 'class_id');
} }
} }

160
niucloud/app/service/admin/customer_resources/CustomerResourcesService.php

@ -15,6 +15,8 @@ use app\model\campus_person_role\CampusPersonRole;
use app\model\course_schedule\CourseSchedule; use app\model\course_schedule\CourseSchedule;
use app\model\customer_resource_changes\CustomerResourceChanges; use app\model\customer_resource_changes\CustomerResourceChanges;
use app\model\customer_resources\CustomerResources; use app\model\customer_resources\CustomerResources;
use app\model\member\Member;
use app\model\member\MemberLabel;
use app\model\order_table\OrderTable; use app\model\order_table\OrderTable;
use app\model\personnel\Personnel; use app\model\personnel\Personnel;
use app\model\campus\Campus; use app\model\campus\Campus;
@ -22,6 +24,7 @@ use app\model\campus\Campus;
use app\model\resource_sharing\ResourceSharing; use app\model\resource_sharing\ResourceSharing;
use app\model\six_speed\SixSpeed; use app\model\six_speed\SixSpeed;
use app\model\six_speed_modification_log\SixSpeedModificationLog; use app\model\six_speed_modification_log\SixSpeedModificationLog;
use app\model\student_courses\StudentCourses;
use app\service\admin\member\MemberLabelService; use app\service\admin\member\MemberLabelService;
use core\base\BaseAdminService; use core\base\BaseAdminService;
@ -95,9 +98,21 @@ class CustomerResourcesService extends BaseAdminService
return $this->pageQuery($search_model, function ($item, $key) { return $this->pageQuery($search_model, function ($item, $key) {
$item = $this->makeUp($item); $item = $this->makeUp($item);
$sixSpeed = new SixSpeed();
$data = $sixSpeed->where(['resource_id' => $item['id']])->findOrEmpty()->toArray();
$item['six'] = $data;
$member = new Member();
$member_info = $member->where(['member_id' => $item['member_id']])->findOrEmpty()->toArray();
$item['member_info'] = $member_info;
}); });
} }
/** /**
* 获取客户资源信息 * 获取客户资源信息
* @param int $id * @param int $id
@ -415,4 +430,149 @@ class CustomerResourcesService extends BaseAdminService
return $all; return $all;
} }
public function log_list(array $data = [])
{
$customer_resource_changes = new CustomerResourceChanges();
$where = [];
if ($data['customer_resource_id']) {
$where[] = ['a.customer_resource_id', '=', $data['customer_resource_id']];
}
$search_model = $customer_resource_changes
->alias("a")
->join(['school_personnel' => 'b'], 'a.operator_id = b.id', 'left')
->where($where)
->field("a.*,b.name")
->order("a.id asc");
return $this->pageQuery($search_model, function ($item, $key) {
$fieldZhArr = CustomerResources::FieldZh;
$modified_fields = json_decode($item['modified_fields'], true);
$type = [];
foreach ($modified_fields as $key => $value) {
$type[] = $fieldZhArr[$value];
}
$item['type'] = implode("<br>",$type);
$old_values = json_decode($item['old_values'], true);
$new_values = json_decode($item['new_values'], true);
$values = [];
foreach ($old_values as $key => $value) {
$old_value = $this->fields($key,$value);
$new_value = $this->fields($key,$new_values[$key]);
$values[] = $old_value.'->'.$new_value;
}
$item['values'] = implode("<br>",$values);
});
}
public function student_courses(array $data = [])
{
$studentCourses = new StudentCourses();
$where = [];
if ($data['customer_resource_id']) {
$where[] = ['b.user_id', '=', $data['customer_resource_id']];
}
$search_model = $studentCourses
->alias("a")
->join(['school_student' => 'b'], 'a.student_id = b.id', 'left')
->join(['school_course' => 'c'], 'a.course_id = c.id', 'left')
->where($where)
->field("a.*,c.course_name")
->order("a.id desc");
return $this->pageQuery($search_model, function ($item, $key) {
$item['total'] = $item['total_hours'] + $item['gift_hours'];
$item['used'] = $item['use_total_hours'] + $item['use_gift_hours'];
$now = date('Y-m-d'); // 当前日期
if ($now < $item['start_date']) {
$item['status'] = '未进行';
} elseif ($now > $item['end_date']) {
$item['status'] = '已结束';
} else {
$item['status'] = '进行中';
}
});
}
public function order_table(array $data = [])
{
$orderTable = new OrderTable();
$where = [];
if ($data['customer_resource_id']) {
$where[] = ['a.resource_id', '=', $data['customer_resource_id']];
}
$search_model = $orderTable
->alias("a")
->join(['school_course' => 'b'], 'a.course_id = b.id', 'left')
->where($where)
->field("a.*,b.course_name")
->order("a.id desc");
return $this->pageQuery($search_model, function ($item, $key) {
$arr = ['cash' => '现金支付','scan_code' => '扫码支付','subscription' => '订阅支付'];
$item['type'] = $arr[$item['payment_type']];
$item['order_status'] = $item['order_status'] == 'pending' ? '待支付' : '已支付';
});
}
public function fields($filed,$value){
if(!$value){
return '空';
}
$campus = new Campus();
$member_label = new MemberLabel();
switch ($filed) {
case 'initial_intent':
return get_dict_value('preliminarycustomerintention',$value);
break;
case 'source':
return get_dict_value('source',$value);
break;
case 'purchasing_power':
return get_dict_value('customer_purchasing_power',$value);
break;
case 'cognitive_idea':
return get_dict_value('cognitive_concept',$value);
break;
case 'source_channel':
return get_dict_value('SourceChannel',$value);
break;
case 'status':
return get_dict_value('kh_status',$value);
break;
case 'member_label':
$label_name = $member_label->where('label_id','in',$value)->column('label_name');
return implode("-",$label_name);
break;
case 'campus':
return $campus->where(['id' => $value])->value("campus_name");
break;
default:
return $value;
}
}
} }

60
niucloud/app/service/admin/service_logs/ServiceLogsService.php

@ -0,0 +1,60 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\admin\service_logs;
use app\model\service_logs\ServiceLogs;
use core\base\BaseAdminService;
/**
* 学员课时消费记录服务层
* Class StudentCourseUsageService
* @package app\service\admin\student_course_usage
*/
class ServiceLogsService extends BaseAdminService
{
public function __construct()
{
parent::__construct();
$this->model = new ServiceLogs();
}
/**
* 获取学员课时消费记录列表
* @return array
*/
public function getPage(array $data = [])
{
$where = [];
if($data['name']){
$where[] = ['b.name','like','%'.$data['name'].'%'];
}
if($data['score']){
$where[] = ['a.score','=',$data['score']];
}
$search_model = $this->model
->alias("a")
->join(['school_customer_resources' => 'b'],'a.resource_id = b.id','left')
->join(['school_personnel' => 'c'],'a.staff_id = c.id','left')
->join(['school_service' => 'd'],'a.service_id = d.id','left')
->where($where)
->field("a.*,b.name,c.name as staff_name,d.service_name,d.customer_confirmation")
->order("a.id desc");
$list = $this->pageQuery($search_model);
return $list;
}
}

28
niucloud/app/service/admin/student_course_usage/StudentCourseUsageService.php

@ -31,15 +31,31 @@ class StudentCourseUsageService extends BaseAdminService
/** /**
* 获取学员课时消费记录列表 * 获取学员课时消费记录列表
* @param array $where
* @return array * @return array
*/ */
public function getPage(array $where = []) public function getPage(array $data = [])
{ {
$field = 'id,student_course_id,used_hours,usage_date,created_at,updated_at'; $where = [];
$order = 'id desc'; if($data['emergency_contact']){
$where[] = ['c.emergency_contact','like','%'.$data['emergency_contact'].'%'];
$search_model = $this->model->withSearch(["id","student_course_id","used_hours","usage_date"], $where)->field($field)->order($order); }
if($data['student_name']){
$where[] = ['c.name','like','%'.$data['student_name'].'%'];
}
if($data['contact_phone']){
$where[] = ['c.contact_phone','=',$data['contact_phone']];
}
$search_model = $this->model
->alias("a")
->join(['school_student_courses' => 'b'],'a.student_course_id = b.id','left')
->join(['school_student' => 'c'],'b.student_id = c.id','left')
->join(['school_course' => 'd'],'b.course_id = d.id','left')
->where($where)
->field("a.*,c.name as student_name,c.emergency_contact,d.course_name,b.total_hours,ROUND(b.total_hours - b.use_total_hours) as sy_time,ROUND(b.gift_hours - b.use_gift_hours) as gift_hours")
->order("a.id desc");
$list = $this->pageQuery($search_model); $list = $this->pageQuery($search_model);
return $list; return $list;
} }

24
niucloud/app/service/api/apiService/CommonService.php

@ -54,6 +54,15 @@ class CommonService extends BaseApiService
*/ */
public function forgetPassword($phone, $new_password, $user_type){ public function forgetPassword($phone, $new_password, $user_type){
if($user_type == 'personnel'){ if($user_type == 'personnel'){
$data = SysUser::where('username', $phone)->find();
if (!$data){
$res = [
'code' => 0,
'msg' => '用户不存在',
'data' => []
];
return $res;
}
//重置员工(销售/教师)密码 //重置员工(销售/教师)密码
$update = SysUser::where('username', $phone)->update([ $update = SysUser::where('username', $phone)->update([
'password' => create_password($new_password),//创建密码 'password' => create_password($new_password),//创建密码
@ -74,6 +83,15 @@ class CommonService extends BaseApiService
} }
return $res; return $res;
}else{ }else{
$data = Member::where('username', $phone)->find();
if (!$data){
$res = [
'code' => 0,
'msg' => '用户不存在',
'data' => []
];
return $res;
}
//重置用户(学生)密码 //重置用户(学生)密码
$update = Member::where('username', $phone)->update([ $update = Member::where('username', $phone)->update([
'password' => create_password($new_password),//创建密码 'password' => create_password($new_password),//创建密码
@ -125,12 +143,18 @@ class CommonService extends BaseApiService
} }
return [ return [
// 返回发生更改的字段名数组
'changed_fields' => $changedFields, 'changed_fields' => $changedFields,
// 返回旧数据中的更改字段及其值
'old_values' => $oldChanges, 'old_values' => $oldChanges,
// 返回新数据中的更改字段及其值
'new_values' => $newChanges, 'new_values' => $newChanges,
// 将 changed_fields 转换为 JSON 格式,保留中文字符
'changed_fields_json' => json_encode($changedFields, JSON_UNESCAPED_UNICODE), 'changed_fields_json' => json_encode($changedFields, JSON_UNESCAPED_UNICODE),
// 将 old_changes 转换为 JSON 格式,保留中文字符
'old_values_json' => json_encode($oldChanges, JSON_UNESCAPED_UNICODE), 'old_values_json' => json_encode($oldChanges, JSON_UNESCAPED_UNICODE),
// 将 new_changes 转换为 JSON 格式,保留中文字符
'new_values_json' => json_encode($newChanges, JSON_UNESCAPED_UNICODE) 'new_values_json' => json_encode($newChanges, JSON_UNESCAPED_UNICODE)
]; ];
} }

43
niucloud/app/service/api/apiService/CourseService.php

@ -50,9 +50,8 @@ class CourseService extends BaseApiService
$query->select(); $query->select();
},'venue' => function($query) { },'venue' => function($query) {
$query->select(); $query->select();
}]); },'campus','studentCourses']);
$list = $this->pageQuery($search_model); $list = $this->pageQuery($search_model);
$PersonCourseSchedule = new PersonCourseSchedule();
foreach ($list['data'] as $k => $v) { foreach ($list['data'] as $k => $v) {
$student = Db::name('person_course_schedule') $student = Db::name('person_course_schedule')
->alias('pcs') ->alias('pcs')
@ -93,7 +92,7 @@ class CourseService extends BaseApiService
->alias('sc') ->alias('sc')
->where('sc.course_id', $list['id']) ->where('sc.course_id', $list['id'])
->join('school_student_course_usage sscu', 'sc.id = sscu.student_course_id') ->join('school_student_course_usage sscu', 'sc.id = sscu.student_course_id')
->field('sc.student_id,sc.end_date') ->field('sc.student_id,sc.end_date,sc.end_date,sc.start_date,sc.course_id')
->select()->toArray(); ->select()->toArray();
foreach ($student_courses as &$v){ foreach ($student_courses as &$v){
$student = Db::name('student') $student = Db::name('student')
@ -138,6 +137,44 @@ class CourseService extends BaseApiService
} }
public function classList($data)
{
$CourseSchedule = new CourseSchedule();
$search_model = $CourseSchedule
->where('coach_id', $data)
->with(['course' => function($query) {
$query->with(['studentCourses' => function($query) {
$query->select();
}]);
},'venue' => function($query) {
$query->select();
},'coach' => function($query) {
$query->select();
},'campus']);
$list = $this->pageQuery($search_model);
foreach ($list['data'] as &$v){
$student = Db::name('person_course_schedule')
->alias('pcs')
->where('pcs.schedule_id', $v['id'])
->join('school_student st', 'pcs.student_id = st.id')
->join('school_customer_resources cr', 'st.user_id = cr.id')
->join('school_member sm', 'cr.member_id = sm.member_id')
->field('st.name, sm.headimg as avatar')
->select();
$v['student'] = $student;
}
foreach ($list['data'] as &$v) {
$student_courses = Db::name('student_courses')
->alias('sc')
->where('sc.course_id', $v['id'])
->join('school_student_course_usage sscu', 'sc.id = sscu.student_course_id')
->field('sc.student_id,sc.end_date,sc.end_date,sc.start_date,sc.course_id')
->select()->toArray();
$v['student_courses'] = $student_courses;
}
return $list;
}
//获取添加学员列表 //获取添加学员列表
public function StudentList($id) public function StudentList($id)
{ {

117
niucloud/app/service/api/apiService/CustomerResourcesService.php

@ -36,6 +36,37 @@ class CustomerResourcesService extends BaseApiService
parent::__construct(); parent::__construct();
} }
//获取客户资源详情
public function getInfo(array $where,string $field = '*'){
$res = [
'code' => 0,
'msg' => '操作失败',
'data' => []
];
$model = new CustomerResources();
if(!empty($where['member_id'])){
$model = $model->where('member_id', $where['member_id']);
}
$data = $model->field($field)
->with([
'memberHasOne',
'resourceSharingHasMany'
])
->append([
'gender_name',
'initial_intent_name'
])
->find();
if ($data){
$data = $data->toArray();
$res['code'] = 1;
$res['data'] = $data;
}else{
$res['msg'] = '暂无数据';
}
return $res;
}
//获取全部客户资源数据 //获取全部客户资源数据
public function getAll(array $where,string $field = '*') public function getAll(array $where,string $field = '*')
{ {
@ -280,6 +311,92 @@ class CustomerResourcesService extends BaseApiService
} }
} }
//客户资源(学生个人资料)-编辑
public function editInfo(array $where, array $data)
{
$res = [
'code' => 0,
'msg' => '操作失败',
'data' => []
];
if (!$where) {
$res['msg'] = '查询条件不能为空';
return $res;
}
$customer_resources_data = [
'name' => $data['name'], // 姓名
'gender' => $data['gender'], // 性别(male:男, female:女)
'age' => $data['age'], // 年龄
'phone_number' => $data['phone_number'], // 手机号
];
$date = date('Y-m-d H:i:s');
$customer_resources_data['updated_at'] = $date;
//开启事物
Db::startTrans();
try {
$customer_resources = CustomerResources::where('member_id', $where['member_id'])->find();
if ($customer_resources) {
$customer_resources = $customer_resources->toArray();
}
$update_1 = CustomerResources::where('id', $customer_resources['id'])->update($customer_resources_data);//客户资源表
if (!$update_1) {
Db::rollback();
return $res;
}
//更新学生账户登录表
$member_data = [
'username' => $data['phone_number'],
'mobile' => $data['phone_number'],
'update_time' => time()
];
if (!empty($data['headimg'])) {
$member_data['headimg'] = $data['headimg'];
}
$update_member = Member::where('member_id', $where['member_id'])->update($member_data);
if (!$update_member) {
Db::rollback();
return $res;
}
//更近客户资源日志表
$compareData = (new CommonService)->compareData($customer_resources, $customer_resources_data);
if ($compareData['changed_fields']) {
$data = [
"customer_resource_id" => $customer_resources['id'],//客户资源的ID
"operator_id" => 0,//操作人的ID
"campus_id" => 0,//操作人校区的ID|如果这人有2校区就填0
"modified_fields" => $compareData['changed_fields_json'],//修改的哪些字段
"old_values" => $compareData['old_values_json'],//修改前的值
"new_values" => $compareData['new_values_json'],//修改后的值
];
$id = CustomerResourceChanges::insertGetId($data);
if (!$id) {
Db::rollback();
return $res;
}
}
Db::commit();
$res = [
'code' => 1,
'msg' => '操作成功'
];
return $res;
} catch (\Exception $exception) {
Db::rollback();
return $res;
}
}
//客户资源-获取客户资源修改记录列表 //客户资源-获取客户资源修改记录列表
public function getCustomerResourceChangesEditLog(array $where) public function getCustomerResourceChangesEditLog(array $where)
{ {

98
niucloud/app/service/api/apiService/PersonCourseScheduleService.php

@ -0,0 +1,98 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\api\apiService;
use app\model\chat_friends\ChatFriends;
use app\model\course_schedule\CourseSchedule;
use app\model\person_course_schedule\PersonCourseSchedule;
use core\base\BaseApiService;
use think\facade\Db;
/**
* 测试-控制器服务层
* Class MemberService
* @package app\service\api\member
*/
class PersonCourseScheduleService extends BaseApiService
{
public function __construct()
{
parent::__construct();
}
//查询列表
public function getList(array $where)
{
$page_params = $this->getPageParam();//获取请求参数中的页码+分页数
$page = $page_params['page'];
$limit = $page_params['limit'];
$model = new PersonCourseSchedule();
//判断有没有客户资源id
if (!empty($where['resources_id'])) {
$model = $model->where('resources_id', $where['resources_id']);
}
$schedule_id = $model->distinct(true)->column('schedule_id');//课程安排id
if(!$schedule_id){
return [];
}
$data = CourseSchedule::whereIn('id', $schedule_id)
->order('course_date','desc')
->with([
'venue',//场地
'campus',//校区
'course',//课程
])
->paginate([
'list_rows' => $limit,
'page' => $page,
])->toArray();
return $data;
}
//查询详情
public function getTestInfo(array $where)
{
$model = new ChatFriends();
//判断用没有员工id
if (!empty($where['personnel_id'])) {
$model = $model->where('personnel_id', $where['personnel_id']);
}
if (!empty($where['customer_resources_id'])) {
$model = $model->where('customer_resources_id', $where['customer_resources_id']);
}
$data = $model->find();
if ($data) {
$data = $data->toArray();
$res = [
'code' => 1,
'msg' => '操作成功',
'data' => $data
];
return $res;
} else {
$res = [
'code' => 0,
'msg' => '暂无数据',
'data' => []
];
return $res;
}
}
}

115
niucloud/app/service/api/apiService/PhysicalTestService.php

@ -0,0 +1,115 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\api\apiService;
use app\model\campus\Campus;
use app\model\campus_person_role\CampusPersonRole;
use app\model\chat_friends\ChatFriends;
use app\model\physical_test\PhysicalTest;
use core\base\BaseApiService;
/**
* 体测报告-控制器服务层
* Class MemberService
* @package app\service\api\member
*/
class PhysicalTestService extends BaseApiService
{
public function __construct()
{
parent::__construct();
}
//查询列表
public function getList(array $where,string $field = '*')
{
$page_params = $this->getPageParam();//获取请求参数中的页码+分页数
$page = $page_params['page'];
$limit = $page_params['limit'];
$model = new PhysicalTest();
//判断用没有员工id
if (!empty($where['resource_id'])) {
$model = $model->where('resource_id', $where['resource_id']);
}
$data = $model
->field($field)
->order('id','desc')
->append([
'customerResources'
])
->with([
'customerResourcesHasOne'
])
->paginate([
'list_rows' => $limit,
'page' => $page,
])->toArray();
foreach ($data['data'] as &$v) {
$age = $v['age'];//年龄
$gender = $v['customerResourcesHasOne']['gender'] == 'female' ? 2:1 ;//性别( 1:男,2:女)
$height = $v['height'];//身高
$weight = $v['weight'];//体重
$v['calculateChildHealthScore'] = calculateChildHealthScore($age, $gender, $height, $weight);//综合评分
}
return $data;
}
//查询详情
public function getInfo(array $where,string $field = '*')
{
$model = new PhysicalTest();
//判断用没有体测报告id
if (!empty($where['id'])) {
$model = $model->where('id', $where['id']);
}
$data = $model
->field($field)
->append([
'customerResources'
])
->with([
'customerResourcesHasOne'
])
->find();
if ($data) {
$data = $data->toArray();
$age = $data['age'];//年龄
$gender = $data['customerResourcesHasOne']['gender'] == 'female' ? 2 : 1;//性别( 1:男,2:女)
$height = $data['height'];//身高
$weight = $data['weight'];//体重
$data['calculateChildHealthScore'] = calculateChildHealthScore($age, $gender, $height, $weight);//综合评分
$res = [
'code' => 1,
'msg' => '操作成功',
'data' => $data
];
return $res;
} else {
$res = [
'code' => 0,
'msg' => '暂无数据',
'data' => []
];
return $res;
}
}
}

95
niucloud/app/service/api/apiService/TestService.php

@ -0,0 +1,95 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\api\apiService;
use app\model\campus\Campus;
use app\model\campus_person_role\CampusPersonRole;
use app\model\chat_friends\ChatFriends;
use app\model\chat_messages\ChatMessages;
use app\model\dict\Dict;
use core\base\BaseApiService;
use think\facade\Db;
/**
* 测试-控制器服务层
* Class MemberService
* @package app\service\api\member
*/
class TestService extends BaseApiService
{
public function __construct()
{
parent::__construct();
}
//查询列表
public function getTestList(array $where)
{
$page_params = $this->getPageParam();//获取请求参数中的页码+分页数
$page = $page_params['page'];
$limit = $page_params['limit'];
$model = new ChatFriends();
//判断用没有员工id
if (!empty($where['personnel_id'])) {
$model = $model->where('personnel_id', $where['personnel_id']);
}
if (!empty($where['customer_resources_id'])) {
$model = $model->where('customer_resources_id', $where['customer_resources_id']);
}
$data = $model
->with([
'personnel',
'customer',
])
->paginate([
'list_rows' => $limit,
'page' => $page,
])->toArray();
return $data;
}
//查询详情
public function getTestInfo(array $where)
{
$model = new ChatFriends();
//判断用没有员工id
if (!empty($where['personnel_id'])) {
$model = $model->where('personnel_id', $where['personnel_id']);
}
if (!empty($where['customer_resources_id'])) {
$model = $model->where('customer_resources_id', $where['customer_resources_id']);
}
$data = $model->find();
if ($data) {
$data = $data->toArray();
$res = [
'code' => 1,
'msg' => '操作成功',
'data' => $data
];
return $res;
} else {
$res = [
'code' => 0,
'msg' => '暂无数据',
'data' => []
];
return $res;
}
}
}

156
niucloud/app/service/api/apiService/jlClassService.php

@ -0,0 +1,156 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\api\apiService;
use app\model\class_grade\ClassGrade;
use app\model\student\Student;
use app\model\assignment\Assignment;
use app\model\course\Course;
use core\base\BaseApiService;
/**
* 考勤管理服务层
* Class MemberService
* @package app\service\api\member
*/
class jlClassService extends BaseApiService
{
public function __construct()
{
parent::__construct();
$this->model = (new ClassGrade());
}
//列表
public function list($id,$data)
{
$order = 'id desc';
$where = [];
if ($data['name'] !== '') {
$where[] = ['name','like','%'.$data['name'].'%'];
}
$search_model = $this->model->where('head_coach', $id)->where($where)->order($order)
->with(['classPersonnelRel' => function($query) {
$query->with(['student' => function($query) {
$query->with(['customerResources' => function($query) {
$query->with(['member' => function($query) {
$query->select();
}]);
}]);
},'studentCourses']);
},'personnelAll']);
$list = $this->pageQuery($search_model);
foreach ($list['data'] as &$v){
if (count($v['classPersonnelRel']) > 0) {
$now = time();
$count = 0;
foreach ($v['classPersonnelRel'] as $item) {
if (isset($item['end_date'])) {
$endTime = strtotime($item['end_date']);
if ($endTime > $now && $endTime <= $now + 7 * 86400) {
$count++;
}
}
}
$v['end_count'] = $count;
} else {
$v['end_count'] = 0;
}
}
return $list;
}
public function info($data)
{
$search_model = $this->model->where('id', $data)
->with(['classPersonnelRel' => function($query) {
$query->with(['student' => function($query) {
$query->with(['customerResources' => function($query) {
$query->with(['member' => function($query) {
$query->select();
}]);
}]);
},'studentCourses','studentCoursesInfo']);
},'personnelAll', 'personnelName']);
$list = $search_model->find();
if (count($list['classPersonnelRel']) > 0) {
$now = time();
$count = 0;
foreach ($list['classPersonnelRel'] as $item) {
if (isset($item['end_date'])) {
$endTime = strtotime($item['end_date']);
if ($endTime > $now && $endTime <= $now + 7 * 86400) {
$count++;
}
}
}
$v['end_count'] = $count;
} else {
$v['end_count'] = 0;
}
return $list;
}
public function jlStudentsInfo($data)
{
$Student = new Student();
$res = $Student->where('id',$data)->with(['customerResources' => function($query) {
$query->with(['member' => function($query) {
$query->select();
}]);
}]);
$res = $res->find();
return $res;
}
public function PhysicalTestList($data)
{
$resource_id = $data;
$where = [
'resource_id' => $resource_id,
];
$physical_test = (new PhysicalTestService())->getList($where);
$res['physical_test'] = $physical_test;
return $res;
}
public function GetClassesList()
{
$res = $this->model->where('status',1)->select()->toArray();
return $res;
}
public function GetCoursesList()
{
$Course = new Course();
$res = $Course->select()->toArray();
return $res;
}
public function GetStudentList()
{
$Student = new Student();
$res = $Student->where('status', 1)->select()->toArray();
return $res;
}
public function addPublishJob($data)
{
$Assignment = new Assignment();
$res = $Assignment->create($data);
return $res;
}
}

24
niucloud/app/service/school_approval/SchoolApprovalProcessService.php

@ -3,6 +3,7 @@ declare(strict_types=1);
namespace app\service\school_approval; namespace app\service\school_approval;
use app\model\personnel\Personnel;
use app\model\school_approval\SchoolApprovalConfig; use app\model\school_approval\SchoolApprovalConfig;
use app\model\school_approval\SchoolApprovalConfigNode; use app\model\school_approval\SchoolApprovalConfigNode;
use app\model\school_approval\SchoolApprovalParticipants; use app\model\school_approval\SchoolApprovalParticipants;
@ -26,10 +27,13 @@ class SchoolApprovalProcessService
*/ */
public function getList(array $where = [], int $page = 1, int $limit = 10): array public function getList(array $where = [], int $page = 1, int $limit = 10): array
{ {
$field = 'id, process_name, applicant_id, application_time, current_approver_id, approval_status, approval_time, remarks, created_at, updated_at'; $field = 'a.*,b.name as applicant_name,c.name as current_approver_name';
$order = 'id desc'; $order = 'a.id desc';
$list = (new SchoolApprovalProcess()) $list = (new SchoolApprovalProcess())
->alias("a")
->join(['school_personnel' => 'b'],'a.applicant_id = b.id','left')
->join(['school_personnel' => 'c'],'a.current_approver_id = c.id','left')
->where($where) ->where($where)
->field($field) ->field($field)
->order($order) ->order($order)
@ -52,12 +56,24 @@ class SchoolApprovalProcessService
*/ */
public function getInfo(int $id): array public function getInfo(int $id): array
{ {
$info = (new SchoolApprovalProcess())->with(['participants'])->where(['id' => $id])->find(); $info = (new SchoolApprovalProcess())
->alias("a")
->join(['school_personnel' => 'b'],'a.applicant_id = b.id','left')
->join(['school_personnel' => 'c'],'a.current_approver_id = c.id','left')
->with(['participants'])
->where(['a.id' => $id])
->field('a.*,b.name as applicant_name,c.name as current_approver_name')
->find();
if (empty($info)) { if (empty($info)) {
return []; return [];
} }
$info = $info->toArray();
$Personnel = new Personnel();
foreach ($info['participants'] as $key => $value) {
$info['participants'][$key]['name'] = $Personnel->where(['id' => $value['participant_id']])->value('name');
}
return $info->toArray(); return $info;
} }
/** /**

Loading…
Cancel
Save