Browse Source

处理冲突

master
王泽彦 10 months ago
parent
commit
ef77b7c436
  1. 31
      admin/src/app/api/market_performance.ts
  2. 35
      admin/src/app/api/person_course_schedule.ts
  3. 2
      admin/src/app/api/service.ts
  4. 7
      admin/src/app/api/sys.ts
  5. 26
      admin/src/app/lang/zh-cn/market_performance.market_performance.json
  6. 34
      admin/src/app/lang/zh-cn/person_course_schedule.person_course_schedule.json
  7. 11
      admin/src/app/views/classroom/classroom.vue
  8. 3
      admin/src/app/views/customer_resources/components/fp.vue
  9. 420
      admin/src/app/views/market_performance/components/market-performance-edit.vue
  10. 434
      admin/src/app/views/market_performance/market_performance.vue
  11. 436
      admin/src/app/views/person_course_schedule/components/person-course-schedule-edit.vue
  12. 469
      admin/src/app/views/person_course_schedule/person_course_schedule.vue
  13. 739
      admin/src/app/views/physical_test/components/physical-test-edit.vue
  14. 52
      admin/src/app/views/scsjtj/components/BarChart.vue
  15. 17
      admin/src/app/views/scsjtj/components/Card.vue
  16. 69
      admin/src/app/views/scsjtj/components/PieChart.vue
  17. 127
      admin/src/app/views/scsjtj/scsjtj.vue
  18. 28
      admin/src/app/views/service/components/service-edit.vue
  19. 25
      admin/src/app/views/service/service.vue
  20. 1
      admin/src/app/views/student/student.vue
  21. 2
      admin/src/app/views/venue/venue.vue
  22. 5
      niucloud/app/adminapi/controller/campus/Campus.php
  23. 4
      niucloud/app/adminapi/controller/classroom/Classroom.php
  24. 1
      niucloud/app/adminapi/controller/customer_resources/CustomerResources.php
  25. 6
      niucloud/app/adminapi/controller/market_performance/MarketPerformance.php
  26. 39
      niucloud/app/adminapi/controller/person_course_schedule/PersonCourseSchedule.php
  27. 1
      niucloud/app/adminapi/controller/student/Student.php
  28. 15
      niucloud/app/adminapi/controller/sys/System.php
  29. 1
      niucloud/app/adminapi/route/market_performance.php
  30. 8
      niucloud/app/adminapi/route/person_course_schedule.php
  31. 1
      niucloud/app/adminapi/route/service.php
  32. 3
      niucloud/app/adminapi/route/sys.php
  33. 7
      niucloud/app/api/controller/apiController/CustomerResources.php
  34. 8
      niucloud/app/api/controller/upload/Upload.php
  35. 2
      niucloud/app/api/route/route.php
  36. 4
      niucloud/app/model/chat_friends/ChatFriends.php
  37. 18
      niucloud/app/model/market_performance/MarketPerformance.php
  38. 82
      niucloud/app/model/person_course_schedule/PersonCourseSchedule.php
  39. 8
      niucloud/app/service/admin/campus/CampusService.php
  40. 8
      niucloud/app/service/admin/classroom/ClassroomService.php
  41. 15
      niucloud/app/service/admin/customer_resources/CustomerResourcesService.php
  42. 4
      niucloud/app/service/admin/market_performance/MarketPerformanceService.php
  43. 51
      niucloud/app/service/admin/person_course_schedule/PersonCourseScheduleService.php
  44. 2
      niucloud/app/service/admin/student/StudentService.php
  45. 57
      niucloud/app/service/admin/sys/SystemService.php
  46. 7
      niucloud/app/service/api/apiService/ChatService.php
  47. 41
      niucloud/app/service/api/apiService/CustomerResourcesService.php
  48. 6
      niucloud/app/service/api/apiService/ResourceSharingService.php
  49. 4
      niucloud/app/service/api/upload/UploadService.php
  50. 18
      niucloud/app/validate/person_course_schedule/PersonCourseSchedule.php

31
admin/src/app/api/market_performance.ts

@ -1,5 +1,7 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- market_performance
/**
*
@ -7,7 +9,7 @@ import request from '@/utils/request'
* @returns
*/
export function getMarketPerformanceList(params: Record<string, any>) {
return request.get(`market_performance/market_performance`, { params })
return request.get(`market_performance/market_performance`, {params})
}
/**
@ -16,7 +18,7 @@ export function getMarketPerformanceList(params: Record<string, any>) {
* @returns
*/
export function getMarketPerformanceInfo(id: number) {
return request.get(`market_performance/market_performance/${id}`)
return request.get(`market_performance/market_performance/${id}`);
}
/**
@ -25,10 +27,7 @@ export function getMarketPerformanceInfo(id: number) {
* @returns
*/
export function addMarketPerformance(params: Record<string, any>) {
return request.post('market_performance/market_performance', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
return request.post('market_performance/market_performance', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
@ -38,11 +37,7 @@ export function addMarketPerformance(params: Record<string, any>) {
* @returns
*/
export function editMarketPerformance(params: Record<string, any>) {
return request.put(
`market_performance/market_performance/${params.id}`,
params,
{ showErrorMessage: true, showSuccessMessage: true }
)
return request.put(`market_performance/market_performance/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
@ -51,17 +46,13 @@ export function editMarketPerformance(params: Record<string, any>) {
* @returns
*/
export function deleteMarketPerformance(id: number) {
return request.delete(`market_performance/market_performance/${id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
return request.delete(`market_performance/market_performance/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
export function getWithPersonnelList(params: Record<string, any>) {
return request.get('market_performance/personnel_all', { params })
}
export function getWithCampusList(params: Record<string, any>) {
return request.get('market_performance/campus_all', { params })
export function getWithPersonnelList(params: Record<string,any>){
return request.get('market_performance/personnel_all', {params})
}export function getWithCampusList(params: Record<string,any>){
return request.get('market_performance/campus_all', {params})
}
// USER_CODE_END -- market_performance

35
admin/src/app/api/person_course_schedule.ts

@ -1,5 +1,7 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- person_course_schedule
/**
*
@ -7,9 +9,7 @@ import request from '@/utils/request'
* @returns
*/
export function getPersonCourseScheduleList(params: Record<string, any>) {
return request.get(`person_course_schedule/person_course_schedule`, {
params,
})
return request.get(`person_course_schedule/person_course_schedule`, {params})
}
/**
@ -18,7 +18,7 @@ export function getPersonCourseScheduleList(params: Record<string, any>) {
* @returns
*/
export function getPersonCourseScheduleInfo(id: number) {
return request.get(`person_course_schedule/person_course_schedule/${id}`)
return request.get(`person_course_schedule/person_course_schedule/${id}`);
}
/**
@ -27,10 +27,7 @@ export function getPersonCourseScheduleInfo(id: number) {
* @returns
*/
export function addPersonCourseSchedule(params: Record<string, any>) {
return request.post('person_course_schedule/person_course_schedule', params, {
showErrorMessage: true,
showSuccessMessage: true,
})
return request.post('person_course_schedule/person_course_schedule', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
@ -40,11 +37,7 @@ export function addPersonCourseSchedule(params: Record<string, any>) {
* @returns
*/
export function editPersonCourseSchedule(params: Record<string, any>) {
return request.put(
`person_course_schedule/person_course_schedule/${params.id}`,
params,
{ showErrorMessage: true, showSuccessMessage: true }
)
return request.put(`person_course_schedule/person_course_schedule/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
@ -53,14 +46,16 @@ export function editPersonCourseSchedule(params: Record<string, any>) {
* @returns
*/
export function deletePersonCourseSchedule(id: number) {
return request.delete(`person_course_schedule/person_course_schedule/${id}`, {
showErrorMessage: true,
showSuccessMessage: true,
})
return request.delete(`person_course_schedule/person_course_schedule/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
export function xkPersonCourseSchedule(id: number) {
return request.delete(`person_course_schedule/xk/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
/**获取试课人员列表 */
export function getTryCoursePerson(id: number) {
return request.get(`person_course_schedule/get_try_course_person/${id}`)
export function getWithCustomerResourcesList(params: Record<string,any>){
return request.get('person_course_schedule/customer_resources_all', {params})
}
// USER_CODE_END -- person_course_schedule

2
admin/src/app/api/service.ts

@ -2,6 +2,8 @@ import request from '@/utils/request'
// USER_CODE_BEGIN -- service
/**
*

7
admin/src/app/api/sys.ts

@ -790,4 +790,9 @@ export function getHome(params: Record<string, any>) {
export function setDocument(params: Record<string, any>) {
return request.post('sys/document/document', params)
}
}
export function getScsjtj(params: Record<string, any>) {
return request.post('sys/scsjtj', params)
}

26
admin/src/app/lang/zh-cn/market_performance.market_performance.json

@ -1,13 +1,15 @@
{
"personnelId": "人员",
"personnelIdPlaceholder": "请输入人员",
"campusId": "校区",
"campusIdPlaceholder": "全部",
"performanceAmount": "绩效金额",
"performanceAmountPlaceholder": "请输入绩效金额",
"addMarketPerformance": "添加市场绩效",
"updateMarketPerformance": "编辑市场绩效",
"marketPerformanceDeleteTips": "确定要删除该数据吗?",
"startDate": "请选择开始时间",
"endDate": "请选择结束时间"
}
"personnelId":"人员",
"personnelIdPlaceholder":"请输入人员",
"campusId":"校区",
"campusIdPlaceholder":"全部",
"performanceAmount":"绩效金额",
"performanceAmountPlaceholder":"请输入绩效金额",
"createdAt":"创建时间",
"createdAtPlaceholder":"请输入创建时间",
"addMarketPerformance":"添加市场绩效",
"updateMarketPerformance":"编辑市场绩效",
"marketPerformanceDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
}

34
admin/src/app/lang/zh-cn/person_course_schedule.person_course_schedule.json

@ -1,19 +1,17 @@
{
"id": "关系编号",
"idPlaceholder": "请输入关系编号",
"personId": "人员或资源ID",
"personIdPlaceholder": "请输入人员或资源ID",
"personType": "人员类型: student-正式学员, customer_resource-客户资源",
"personTypePlaceholder": "请输入人员类型: student-正式学员, customer_resource-客户资源",
"scheduleId": "课程安排ID",
"scheduleIdPlaceholder": "请输入课程安排ID",
"courseDate": "上课日期",
"courseDatePlaceholder": "请输入上课日期",
"timeSlot": "上课时段",
"timeSlotPlaceholder": "请输入上课时段",
"addPersonCourseSchedule": "添加人员与课程安排关系",
"updatePersonCourseSchedule": "编辑人员与课程安排关系",
"personCourseScheduleDeleteTips": "确定要删除该数据吗?",
"startDate": "请选择开始时间",
"endDate": "请选择结束时间"
}
"personId":"资源",
"personIdPlaceholder":"全部",
"personType":"人员类型",
"personTypePlaceholder":"请输入人员类型",
"scheduleId":"课程类型",
"scheduleIdPlaceholder":"请输入课程类型",
"courseDate":"上课时间",
"courseDatePlaceholder":"请输入上课时间",
"timeSlot":"上课时段",
"timeSlotPlaceholder":"请输入上课时段",
"addPersonCourseSchedule":"添加人员与课程安排关系",
"updatePersonCourseSchedule":"编辑人员与课程安排关系",
"personCourseScheduleDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
}

11
admin/src/app/views/classroom/classroom.vue

@ -221,6 +221,8 @@
<el-button type="primary" link @click="deleteEvent(row.id)"
>{{ t('delete') }}
</el-button>
<el-button type="primary" link @click="classEvent(row.id)">学员</el-button>
</template>
</el-table-column>
</el-table>
@ -253,8 +255,9 @@ import {
} from '@/app/api/classroom'
import { ElMessageBox, FormInstance } from 'element-plus'
import Edit from '@/app/views/classroom/components/classroom-edit.vue'
import { useRoute } from 'vue-router'
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const pageName = route.meta.title
@ -275,6 +278,12 @@ let classroomTable = reactive({
},
})
const classEvent = (class_id : number) => {
console.log(class_id);
router.push({ path: '/student/student', query: { class_id: class_id } })
}
const searchFormRef = ref<FormInstance>()
//

3
admin/src/app/views/customer_resources/components/fp.vue

@ -20,6 +20,7 @@
v-model="formData.shared_by"
clearable
placeholder="请选择分配人员"
filterable
>
<el-option label="请选择" value=""></el-option>
<el-option
@ -99,7 +100,7 @@ const confirm = async (formEl: FormInstance | undefined) => {
const consultantList = ref([] as any[])
const setConsultantList = async () => {
consultantList.value = await (await getWithPersonnelList({ role_id: 2 })).data
consultantList.value = await (await getWithPersonnelList({ role_id: 2 ,dept_id:2})).data
}
setConsultantList()

420
admin/src/app/views/market_performance/components/market-performance-edit.vue

@ -1,231 +1,189 @@
<template>
<el-dialog
v-model="showDialog"
:title="
formData.id ? t('updateMarketPerformance') : t('addMarketPerformance')
"
width="50%"
class="diy-dialog-wrap"
:destroy-on-close="true"
>
<el-form
:model="formData"
label-width="120px"
ref="formRef"
:rules="formRules"
class="page-form"
v-loading="loading"
>
<el-form-item :label="t('personnelId')">
<el-select
class="input-width"
v-model="formData.personnel_id"
clearable
:placeholder="t('personnelIdPlaceholder')"
>
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in personnelIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('campusId')">
<el-select
class="input-width"
v-model="formData.campus_id"
clearable
:placeholder="t('campusIdPlaceholder')"
>
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in campusIdList"
:key="index"
:label="item['campus_name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('performanceAmount')">
<el-input
v-model="formData.performance_amount"
clearable
:placeholder="t('performanceAmountPlaceholder')"
class="input-width"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import {
addMarketPerformance,
editMarketPerformance,
getMarketPerformanceInfo,
getWithPersonnelList,
getWithCampusList,
} from '@/app/api/market_performance'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
personnel_id: '',
campus_id: '',
performance_amount: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
personnel_id: [
{ required: true, message: t('personnelIdPlaceholder'), trigger: 'blur' },
],
campus_id: [
{ required: true, message: t('campusIdPlaceholder'), trigger: 'blur' },
],
performance_amount: [
{
required: true,
message: t('performanceAmountPlaceholder'),
trigger: 'blur',
},
],
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editMarketPerformance : addMarketPerformance
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data)
.then((res) => {
loading.value = false
showDialog.value = false
emit('complete')
})
.catch((err) => {
loading.value = false
})
}
})
}
//
const personnelIdList = ref([] as any[])
const setPersonnelIdList = async () => {
personnelIdList.value = await (await getWithPersonnelList({})).data
}
setPersonnelIdList()
const campusIdList = ref([] as any[])
const setCampusIdList = async () => {
campusIdList.value = await (await getWithCampusList({})).data
}
setCampusIdList()
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getMarketPerformanceInfo(row.id)).data
if (data)
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (
value &&
!/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
value
)
) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData,
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updateMarketPerformance') : t('addMarketPerformance')" width="50%" class="diy-dialog-wrap" :destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('personnelId')" >
<el-select class="input-width" v-model="formData.personnel_id" clearable :placeholder="t('personnelIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in personnelIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('campusId')" >
<el-select class="input-width" v-model="formData.campus_id" clearable :placeholder="t('campusIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in campusIdList"
:key="index"
:label="item['campus_name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('performanceAmount')" >
<el-input v-model="formData.performance_amount" clearable :placeholder="t('performanceAmountPlaceholder')" class="input-width" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { addMarketPerformance, editMarketPerformance, getMarketPerformanceInfo, getWithPersonnelList, getWithCampusList } from '@/app/api/market_performance'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
personnel_id: '',
campus_id: '',
performance_amount: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
personnel_id: [
{ required: true, message: t('personnelIdPlaceholder'), trigger: 'blur' },
]
,
campus_id: [
{ required: true, message: t('campusIdPlaceholder'), trigger: 'blur' },
]
,
performance_amount: [
{ required: true, message: t('performanceAmountPlaceholder'), trigger: 'blur' },
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editMarketPerformance : addMarketPerformance
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
const personnelIdList = ref([] as any[])
const setPersonnelIdList = async () => {
personnelIdList.value = await (await getWithPersonnelList({})).data
}
setPersonnelIdList()
const campusIdList = ref([] as any[])
const setCampusIdList = async () => {
campusIdList.value = await (await getWithCampusList({})).data
}
setCampusIdList()
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if(row){
const data = await (await getMarketPerformanceInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label{
height: auto !important;
}
</style>

434
admin/src/app/views/market_performance/market_performance.vue

@ -1,240 +1,194 @@
<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>
<!-- <el-button type="primary" @click="addEvent">
{{ t('addMarketPerformance') }}
</el-button> -->
</div>
<el-card
class="box-card !border-none my-[10px] table-search-wrap"
shadow="never"
>
<el-form
:inline="true"
:model="marketPerformanceTable.searchParam"
ref="searchFormRef"
>
<el-form-item :label="t('campusId')" prop="campus_id">
<el-select
class="w-[280px]"
v-model="marketPerformanceTable.searchParam.campus_id"
clearable
:placeholder="t('campusIdPlaceholder')"
>
<el-option
v-for="(item, index) in campusIdList"
:key="index"
:label="item['campus_name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item
:label="t('performanceAmount')"
prop="performance_amount"
>
<el-input
v-model="marketPerformanceTable.searchParam.performance_amount"
:placeholder="t('performanceAmountPlaceholder')"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadMarketPerformanceList()">{{
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="marketPerformanceTable.data"
size="large"
v-loading="marketPerformanceTable.loading"
>
<template #empty>
<span>{{
!marketPerformanceTable.loading ? t('emptyData') : ''
}}</span>
</template>
<el-table-column
prop="personnel_id_name"
:label="t('personnelId')"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="campus_id_name"
:label="t('campusId')"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="performance_amount"
:label="t('performanceAmount')"
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>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="marketPerformanceTable.page"
v-model:page-size="marketPerformanceTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="marketPerformanceTable.total"
@size-change="loadMarketPerformanceList()"
@current-change="loadMarketPerformanceList"
/>
</div>
</div>
<edit
ref="editMarketPerformanceDialog"
@complete="loadMarketPerformanceList"
/>
</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 {
getMarketPerformanceList,
deleteMarketPerformance,
getWithPersonnelList,
getWithCampusList,
} from '@/app/api/market_performance'
import { img } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus'
import Edit from '@/app/views/market_performance/components/market-performance-edit.vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
let marketPerformanceTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
campus_id: '',
performance_amount: '',
},
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
/**
* 获取市场绩效列表
*/
const loadMarketPerformanceList = (page: number = 1) => {
marketPerformanceTable.loading = true
marketPerformanceTable.page = page
getMarketPerformanceList({
page: marketPerformanceTable.page,
limit: marketPerformanceTable.limit,
...marketPerformanceTable.searchParam,
})
.then((res) => {
marketPerformanceTable.loading = false
marketPerformanceTable.data = res.data.data
marketPerformanceTable.total = res.data.total
})
.catch(() => {
marketPerformanceTable.loading = false
})
}
loadMarketPerformanceList()
const editMarketPerformanceDialog: Record<string, any> | null = ref(null)
/**
* 添加市场绩效
*/
const addEvent = () => {
editMarketPerformanceDialog.value.setFormData()
editMarketPerformanceDialog.value.showDialog = true
}
/**
* 编辑市场绩效
* @param data
*/
const editEvent = (data: any) => {
editMarketPerformanceDialog.value.setFormData(data)
editMarketPerformanceDialog.value.showDialog = true
}
/**
* 删除市场绩效
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('marketPerformanceDeleteTips'), t('warning'), {
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}).then(() => {
deleteMarketPerformance(id)
.then(() => {
loadMarketPerformanceList()
})
.catch(() => {})
})
}
const personnelIdList = ref([])
const setPersonnelIdList = async () => {
personnelIdList.value = await (await getWithPersonnelList({})).data
}
setPersonnelIdList()
const campusIdList = ref([])
const setCampusIdList = async () => {
campusIdList.value = await (await getWithCampusList({})).data
}
setCampusIdList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadMarketPerformanceList()
}
</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>
<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>
<!-- <el-button type="primary" @click="addEvent">
{{ t('addMarketPerformance') }}
</el-button> -->
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="marketPerformanceTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('campusId')" prop="campus_id">
<el-select class="w-[280px]" v-model="marketPerformanceTable.searchParam.campus_id" clearable :placeholder="t('campusIdPlaceholder')">
<el-option
v-for="(item, index) in campusIdList"
:key="index"
:label="item['campus_name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('performanceAmount')" prop="performance_amount">
<el-input v-model="marketPerformanceTable.searchParam.performance_amount" :placeholder="t('performanceAmountPlaceholder')" />
</el-form-item>
<el-form-item :label="t('createdAt')" prop="created_at">
<el-date-picker v-model="marketPerformanceTable.searchParam.created_at" type="datetimerange" format="YYYY-MM-DD hh:mm:ss"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadMarketPerformanceList()">{{ 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="marketPerformanceTable.data" size="large" v-loading="marketPerformanceTable.loading">
<template #empty>
<span>{{ !marketPerformanceTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="personnel_id_name" :label="t('personnelId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="campus_id_name" :label="t('campusId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="performance_amount" :label="t('performanceAmount')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="created_at" :label="t('createdAt')" 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>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="marketPerformanceTable.page" v-model:page-size="marketPerformanceTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="marketPerformanceTable.total"
@size-change="loadMarketPerformanceList()" @current-change="loadMarketPerformanceList" />
</div>
</div>
<edit ref="editMarketPerformanceDialog" @complete="loadMarketPerformanceList" />
</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 { getMarketPerformanceList, deleteMarketPerformance, getWithPersonnelList, getWithCampusList } from '@/app/api/market_performance'
import { img } from '@/utils/common'
import { ElMessageBox,FormInstance } from 'element-plus'
import Edit from '@/app/views/market_performance/components/market-performance-edit.vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let marketPerformanceTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam:{
"campus_id":"",
"performance_amount":"",
"created_at":[]
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
/**
* 获取市场绩效列表
*/
const loadMarketPerformanceList = (page: number = 1) => {
marketPerformanceTable.loading = true
marketPerformanceTable.page = page
getMarketPerformanceList({
page: marketPerformanceTable.page,
limit: marketPerformanceTable.limit,
...marketPerformanceTable.searchParam
}).then(res => {
marketPerformanceTable.loading = false
marketPerformanceTable.data = res.data.data
marketPerformanceTable.total = res.data.total
}).catch(() => {
marketPerformanceTable.loading = false
})
}
loadMarketPerformanceList()
const editMarketPerformanceDialog: Record<string, any> | null = ref(null)
/**
* 添加市场绩效
*/
const addEvent = () => {
editMarketPerformanceDialog.value.setFormData()
editMarketPerformanceDialog.value.showDialog = true
}
/**
* 编辑市场绩效
* @param data
*/
const editEvent = (data: any) => {
editMarketPerformanceDialog.value.setFormData(data)
editMarketPerformanceDialog.value.showDialog = true
}
/**
* 删除市场绩效
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('marketPerformanceDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteMarketPerformance(id).then(() => {
loadMarketPerformanceList()
}).catch(() => {
})
})
}
const personnelIdList = ref([])
const setPersonnelIdList = async () => {
personnelIdList.value = await (await getWithPersonnelList({})).data
}
setPersonnelIdList()
const campusIdList = ref([])
const setCampusIdList = async () => {
campusIdList.value = await (await getWithCampusList({})).data
}
setCampusIdList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadMarketPerformanceList()
}
</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>

436
admin/src/app/views/person_course_schedule/components/person-course-schedule-edit.vue

@ -1,227 +1,209 @@
<template>
<el-dialog
v-model="showDialog"
:title="
formData.id
? t('updatePersonCourseSchedule')
: t('addPersonCourseSchedule')
"
width="50%"
class="diy-dialog-wrap"
:destroy-on-close="true"
>
<el-form
:model="formData"
label-width="120px"
ref="formRef"
:rules="formRules"
class="page-form"
v-loading="loading"
>
<el-form-item :label="t('personId')" prop="person_id">
<el-input
v-model="formData.person_id"
clearable
:placeholder="t('personIdPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('personType')" prop="person_type">
<el-input
v-model="formData.person_type"
clearable
:placeholder="t('personTypePlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('scheduleId')" prop="schedule_id">
<el-input
v-model="formData.schedule_id"
clearable
:placeholder="t('scheduleIdPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('courseDate')" prop="course_date">
<el-input
v-model="formData.course_date"
clearable
:placeholder="t('courseDatePlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('timeSlot')" prop="time_slot">
<el-input
v-model="formData.time_slot"
clearable
:placeholder="t('timeSlotPlaceholder')"
class="input-width"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import {
addPersonCourseSchedule,
editPersonCourseSchedule,
getPersonCourseScheduleInfo,
} from '@/app/api/person_course_schedule'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
person_id: '',
person_type: '',
schedule_id: '',
course_date: '',
time_slot: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
person_id: [
{ required: true, message: t('personIdPlaceholder'), trigger: 'blur' },
],
person_type: [
{ required: true, message: t('personTypePlaceholder'), trigger: 'blur' },
],
schedule_id: [
{ required: true, message: t('scheduleIdPlaceholder'), trigger: 'blur' },
],
course_date: [
{ required: true, message: t('courseDatePlaceholder'), trigger: 'blur' },
],
time_slot: [
{ required: true, message: t('timeSlotPlaceholder'), trigger: 'blur' },
],
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editPersonCourseSchedule : addPersonCourseSchedule
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data)
.then((res) => {
loading.value = false
showDialog.value = false
emit('complete')
})
.catch((err) => {
loading.value = false
})
}
})
}
//
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getPersonCourseScheduleInfo(row.id)).data
if (data)
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (
value &&
!/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
value
)
) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData,
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updatePersonCourseSchedule') : t('addPersonCourseSchedule')" width="50%" class="diy-dialog-wrap" :destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('personId')" prop="person_id">
<el-select class="input-width" v-model="formData.person_id" clearable :placeholder="t('personIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in personIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('personType')" prop="person_type">
<el-select class="input-width" v-model="formData.person_type" clearable :placeholder="t('personTypePlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in person_typeList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('scheduleId')" prop="schedule_id">
<el-input v-model="formData.schedule_id" clearable :placeholder="t('scheduleIdPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('courseDate')" prop="course_date">
<el-input v-model="formData.course_date" clearable :placeholder="t('courseDatePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('timeSlot')" prop="time_slot">
<el-input v-model="formData.time_slot" clearable :placeholder="t('timeSlotPlaceholder')" class="input-width" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { addPersonCourseSchedule, editPersonCourseSchedule, getPersonCourseScheduleInfo, getWithCustomerResourcesList } from '@/app/api/person_course_schedule'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
person_id: '',
person_type: '',
schedule_id: '',
course_date: '',
time_slot: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
person_id: [
{ required: true, message: t('personIdPlaceholder'), trigger: 'blur' },
]
,
person_type: [
{ required: true, message: t('personTypePlaceholder'), trigger: 'blur' },
]
,
schedule_id: [
{ required: true, message: t('scheduleIdPlaceholder'), trigger: 'blur' },
]
,
course_date: [
{ required: true, message: t('courseDatePlaceholder'), trigger: 'blur' },
]
,
time_slot: [
{ required: true, message: t('timeSlotPlaceholder'), trigger: 'blur' },
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editPersonCourseSchedule : addPersonCourseSchedule
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
let person_typeList = ref([])
const person_typeDictList = async () => {
person_typeList.value = await (await useDictionary('person_type')).data.dictionary
}
person_typeDictList();
watch(() => person_typeList.value, () => { formData.person_type = person_typeList.value[0].value })
const personIdList = ref([] as any[])
const setPersonIdList = async () => {
personIdList.value = await (await getWithCustomerResourcesList({})).data
}
setPersonIdList()
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if(row){
const data = await (await getPersonCourseScheduleInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label{
height: auto !important;
}
</style>

469
admin/src/app/views/person_course_schedule/person_course_schedule.vue

@ -1,256 +1,213 @@
<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>
<el-button type="primary" @click="addEvent">
{{ t('addPersonCourseSchedule') }}
</el-button>
</div>
<el-card
class="box-card !border-none my-[10px] table-search-wrap"
shadow="never"
>
<el-form
:inline="true"
:model="personCourseScheduleTable.searchParam"
ref="searchFormRef"
>
<el-form-item :label="t('personId')" prop="person_id">
<el-input
v-model="personCourseScheduleTable.searchParam.person_id"
:placeholder="t('personIdPlaceholder')"
/>
</el-form-item>
<el-form-item :label="t('personType')" prop="person_type">
<el-input
v-model="personCourseScheduleTable.searchParam.person_type"
:placeholder="t('personTypePlaceholder')"
/>
</el-form-item>
<el-form-item :label="t('scheduleId')" prop="schedule_id">
<el-input
v-model="personCourseScheduleTable.searchParam.schedule_id"
:placeholder="t('scheduleIdPlaceholder')"
/>
</el-form-item>
<el-form-item :label="t('courseDate')" prop="course_date">
<el-input
v-model="personCourseScheduleTable.searchParam.course_date"
:placeholder="t('courseDatePlaceholder')"
/>
</el-form-item>
<el-form-item :label="t('timeSlot')" prop="time_slot">
<el-input
v-model="personCourseScheduleTable.searchParam.time_slot"
:placeholder="t('timeSlotPlaceholder')"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadPersonCourseScheduleList()">{{
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="personCourseScheduleTable.data"
size="large"
v-loading="personCourseScheduleTable.loading"
>
<template #empty>
<span>{{
!personCourseScheduleTable.loading ? t('emptyData') : ''
}}</span>
</template>
<el-table-column
prop="person_id"
:label="t('personId')"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="person_type"
:label="t('personType')"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="schedule_id"
:label="t('scheduleId')"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="course_date"
:label="t('courseDate')"
min-width="120"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="time_slot"
:label="t('timeSlot')"
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>
<div class="mt-[16px] flex justify-end">
<el-pagination
v-model:current-page="personCourseScheduleTable.page"
v-model:page-size="personCourseScheduleTable.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="personCourseScheduleTable.total"
@size-change="loadPersonCourseScheduleList()"
@current-change="loadPersonCourseScheduleList"
/>
</div>
</div>
<edit
ref="editPersonCourseScheduleDialog"
@complete="loadPersonCourseScheduleList"
/>
</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 {
getPersonCourseScheduleList,
deletePersonCourseSchedule,
} from '@/app/api/person_course_schedule'
import { img } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus'
import Edit from '@/app/views/person_course_schedule/components/person-course-schedule-edit.vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
let personCourseScheduleTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
person_id: '',
person_type: '',
schedule_id: '',
course_date: '',
time_slot: '',
},
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
/**
* 获取人员与课程安排关系列表
*/
const loadPersonCourseScheduleList = (page: number = 1) => {
personCourseScheduleTable.loading = true
personCourseScheduleTable.page = page
getPersonCourseScheduleList({
page: personCourseScheduleTable.page,
limit: personCourseScheduleTable.limit,
...personCourseScheduleTable.searchParam,
})
.then((res) => {
personCourseScheduleTable.loading = false
personCourseScheduleTable.data = res.data.data
personCourseScheduleTable.total = res.data.total
})
.catch(() => {
personCourseScheduleTable.loading = false
})
}
loadPersonCourseScheduleList()
const editPersonCourseScheduleDialog: Record<string, any> | null = ref(null)
/**
* 添加人员与课程安排关系
*/
const addEvent = () => {
editPersonCourseScheduleDialog.value.setFormData()
editPersonCourseScheduleDialog.value.showDialog = true
}
/**
* 编辑人员与课程安排关系
* @param data
*/
const editEvent = (data: any) => {
editPersonCourseScheduleDialog.value.setFormData(data)
editPersonCourseScheduleDialog.value.showDialog = true
}
/**
* 删除人员与课程安排关系
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('personCourseScheduleDeleteTips'), t('warning'), {
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}).then(() => {
deletePersonCourseSchedule(id)
.then(() => {
loadPersonCourseScheduleList()
})
.catch(() => {})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadPersonCourseScheduleList()
}
</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>
<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="personCourseScheduleTable.searchParam" ref="searchFormRef">
<el-form-item label="资源名称" prop="name">
<el-input v-model="personCourseScheduleTable.searchParam.name"
placeholder="请输入资源名称" />
</el-form-item>
<el-form-item label="资源手机号" prop="phone_number">
<el-input v-model="personCourseScheduleTable.searchParam.phone_number"
placeholder="请输入资源手机号" />
</el-form-item>
<el-form-item label="校区" prop="campus_name">
<el-input v-model="personCourseScheduleTable.searchParam.campus_name"
placeholder="请输入校区" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadPersonCourseScheduleList()">{{ 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="personCourseScheduleTable.data" size="large" v-loading="personCourseScheduleTable.loading">
<template #empty>
<span>{{ !personCourseScheduleTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="name" label="资源名称" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column label="人员类型" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in person_typeList">
<div v-if="item.value == row.person_type">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="course_type" label="课程类型" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="course_date" :label="t('courseDate')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="time_slot" :label="t('timeSlot')" 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="deleteEvent(row.id)">请假</el-button>
<el-button type="primary" link @click="xkEvent(row.id)">消课</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="personCourseScheduleTable.page" v-model:page-size="personCourseScheduleTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="personCourseScheduleTable.total"
@size-change="loadPersonCourseScheduleList()" @current-change="loadPersonCourseScheduleList" />
</div>
</div>
<edit ref="editPersonCourseScheduleDialog" @complete="loadPersonCourseScheduleList" />
</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 { getPersonCourseScheduleList, deletePersonCourseSchedule, getWithCustomerResourcesList,xkPersonCourseSchedule} from '@/app/api/person_course_schedule'
import { img } from '@/utils/common'
import { ElMessageBox,FormInstance } from 'element-plus'
import Edit from '@/app/views/person_course_schedule/components/person-course-schedule-edit.vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let personCourseScheduleTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam:{
"name":"",
"phone_number":"",
"campus_name":""
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
const person_typeList = ref([] as any[])
const person_typeDictList = async () => {
person_typeList.value = await (await useDictionary('person_type')).data.dictionary
}
person_typeDictList();
/**
* 获取人员与课程安排关系列表
*/
const loadPersonCourseScheduleList = (page: number = 1) => {
personCourseScheduleTable.loading = true
personCourseScheduleTable.page = page
getPersonCourseScheduleList({
page: personCourseScheduleTable.page,
limit: personCourseScheduleTable.limit,
...personCourseScheduleTable.searchParam
}).then(res => {
personCourseScheduleTable.loading = false
personCourseScheduleTable.data = res.data.data
personCourseScheduleTable.total = res.data.total
}).catch(() => {
personCourseScheduleTable.loading = false
})
}
loadPersonCourseScheduleList()
const editPersonCourseScheduleDialog: Record<string, any> | null = ref(null)
/**
* 添加人员与课程安排关系
*/
const addEvent = () => {
editPersonCourseScheduleDialog.value.setFormData()
editPersonCourseScheduleDialog.value.showDialog = true
}
/**
* 编辑人员与课程安排关系
* @param data
*/
const editEvent = (data: any) => {
editPersonCourseScheduleDialog.value.setFormData(data)
editPersonCourseScheduleDialog.value.showDialog = true
}
/**
* 删除人员与课程安排关系
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm("确定请假吗", t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deletePersonCourseSchedule(id).then(() => {
loadPersonCourseScheduleList()
}).catch(() => {
})
})
}
const xkEvent = (id: number) => {
ElMessageBox.confirm("确定销课吗", t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
xkPersonCourseSchedule(id).then(() => {
loadPersonCourseScheduleList()
}).catch(() => {
})
})
}
const personIdList = ref([])
const setPersonIdList = async () => {
personIdList.value = await (await getWithCustomerResourcesList({})).data
}
setPersonIdList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadPersonCourseScheduleList()
}
</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>

739
admin/src/app/views/physical_test/components/physical-test-edit.vue

@ -1,72 +1,45 @@
<template>
<el-dialog
v-model="showDialog"
:title="formData.id ? t('updatePhysicalTest') : t('addPhysicalTest')"
width="50%"
class="diy-dialog-wrap"
:destroy-on-close="true"
>
<el-form
:model="formData"
label-width="120px"
ref="formRef"
:rules="formRules"
class="page-form"
v-loading="loading"
>
<el-form-item :label="t('resourceId')" prop="resource_id">
<el-select
class="input-width"
v-model="formData.resource_id"
clearable
:placeholder="t('resourceIdPlaceholder')"
>
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in resourceIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('studentId')" prop="student_id">
<el-select
class="input-width"
v-model="formData.student_id"
clearable
:placeholder="t('studentIdPlaceholder')"
>
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in studentIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('height')" prop="height">
<el-input
v-model="formData.height"
clearable
:placeholder="t('heightPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('weight')" prop="weight">
<el-input
v-model="formData.weight"
clearable
:placeholder="t('weightPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('coachId')" prop="coach_id">
<el-dialog v-model="showDialog" :title="formData.id ? t('updatePhysicalTest') : t('addPhysicalTest')" width="50%"
class="diy-dialog-wrap" :destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form"
v-loading="loading">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item :label="t('resourceId')" prop="resource_id">
<el-select class="input-width" v-model="formData.resource_id" clearable
:placeholder="t('resourceIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option v-for="(item, index) in resourceIdList" :key="index" :label="item['name']"
:value="item['id']" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('studentId')" prop="student_id">
<el-select class="input-width" v-model="formData.student_id" clearable
:placeholder="t('studentIdPlaceholder')">
<el-option label="请选择" :value="0"></el-option>
<el-option v-for="(item, index) in studentIdList" :key="index" :label="item['name']"
:value="item['id']" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item :label="t('height')" prop="height">
<el-input v-model="formData.height" clearable :placeholder="t('heightPlaceholder')"
class="input-width" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('weight')" prop="weight">
<el-input v-model="formData.weight" clearable :placeholder="t('weightPlaceholder')"
class="input-width" />
</el-form-item>
</el-col>
</el-row>
<!-- <el-form-item :label="t('coachId')" prop="coach_id">
<el-select
class="input-width"
v-model="formData.coach_id"
@ -81,336 +54,314 @@
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('seatedForwardBend')">
<el-input
v-model="formData.seated_forward_bend"
clearable
:placeholder="t('seatedForwardBendPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('sitUps')">
<el-input
v-model="formData.sit_ups"
clearable
:placeholder="t('sitUpsPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('pushUps')">
<el-input
v-model="formData.push_ups"
clearable
:placeholder="t('pushUpsPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('flamingoBalance')">
<el-input
v-model="formData.flamingo_balance"
clearable
:placeholder="t('flamingoBalancePlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('thirtySecJump')">
<el-input
v-model="formData.thirty_sec_jump"
clearable
:placeholder="t('thirtySecJumpPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('standingLongJump')">
<el-input
v-model="formData.standing_long_jump"
clearable
:placeholder="t('standingLongJumpPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('agilityRun')">
<el-input
v-model="formData.agility_run"
clearable
:placeholder="t('agilityRunPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('balanceBeam')">
<el-input
v-model="formData.balance_beam"
clearable
:placeholder="t('balanceBeamPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('tennisThrow')">
<el-input
v-model="formData.tennis_throw"
clearable
:placeholder="t('tennisThrowPlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('tenMeterShuttleRun')">
<el-input
v-model="formData.ten_meter_shuttle_run"
clearable
:placeholder="t('tenMeterShuttleRunPlaceholder')"
class="input-width"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</el-form-item> -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item :label="t('seatedForwardBend')">
<el-input v-model="formData.seated_forward_bend" clearable
:placeholder="t('seatedForwardBendPlaceholder')" class="input-width" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('sitUps')">
<el-input v-model="formData.sit_ups" clearable :placeholder="t('sitUpsPlaceholder')"
class="input-width" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item :label="t('pushUps')">
<el-input v-model="formData.push_ups" clearable :placeholder="t('pushUpsPlaceholder')"
class="input-width" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('flamingoBalance')">
<el-input v-model="formData.flamingo_balance" clearable
:placeholder="t('flamingoBalancePlaceholder')" class="input-width" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item :label="t('thirtySecJump')">
<el-input v-model="formData.thirty_sec_jump" clearable
:placeholder="t('thirtySecJumpPlaceholder')" class="input-width" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('standingLongJump')">
<el-input v-model="formData.standing_long_jump" clearable
:placeholder="t('standingLongJumpPlaceholder')" class="input-width" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item :label="t('agilityRun')">
<el-input v-model="formData.agility_run" clearable :placeholder="t('agilityRunPlaceholder')"
class="input-width" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('balanceBeam')">
<el-input v-model="formData.balance_beam" clearable :placeholder="t('balanceBeamPlaceholder')"
class="input-width" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item :label="t('tennisThrow')">
<el-input v-model="formData.tennis_throw" clearable :placeholder="t('tennisThrowPlaceholder')"
class="input-width" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('tenMeterShuttleRun')">
<el-input v-model="formData.ten_meter_shuttle_run" clearable
:placeholder="t('tenMeterShuttleRunPlaceholder')" class="input-width" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import {
addPhysicalTest,
editPhysicalTest,
getPhysicalTestInfo,
getWithCustomerResourcesList,
getWithStudentList,
getWithPersonnelList,
} from '@/app/api/physical_test'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
resource_id: '',
student_id: '',
height: '',
weight: '',
coach_id: '',
seated_forward_bend: '',
sit_ups: '',
push_ups: '',
flamingo_balance: '',
thirty_sec_jump: '',
standing_long_jump: '',
agility_run: '',
balance_beam: '',
tennis_throw: '',
ten_meter_shuttle_run: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
resource_id: [
{ required: true, message: t('resourceIdPlaceholder'), trigger: 'blur' },
],
student_id: [
{ required: true, message: t('studentIdPlaceholder'), trigger: 'blur' },
],
height: [
{ required: true, message: t('heightPlaceholder'), trigger: 'blur' },
],
weight: [
{ required: true, message: t('weightPlaceholder'), trigger: 'blur' },
],
coach_id: [
{ required: true, message: t('coachIdPlaceholder'), trigger: 'blur' },
],
seated_forward_bend: [
{
required: true,
message: t('seatedForwardBendPlaceholder'),
trigger: 'blur',
},
],
sit_ups: [
{ required: true, message: t('sitUpsPlaceholder'), trigger: 'blur' },
],
push_ups: [
{ required: true, message: t('pushUpsPlaceholder'), trigger: 'blur' },
],
flamingo_balance: [
{
required: true,
message: t('flamingoBalancePlaceholder'),
trigger: 'blur',
},
],
thirty_sec_jump: [
{
required: true,
message: t('thirtySecJumpPlaceholder'),
trigger: 'blur',
},
],
standing_long_jump: [
{
required: true,
message: t('standingLongJumpPlaceholder'),
trigger: 'blur',
},
],
agility_run: [
{ required: true, message: t('agilityRunPlaceholder'), trigger: 'blur' },
],
balance_beam: [
{ required: true, message: t('balanceBeamPlaceholder'), trigger: 'blur' },
],
tennis_throw: [
{ required: true, message: t('tennisThrowPlaceholder'), trigger: 'blur' },
],
ten_meter_shuttle_run: [
{
required: true,
message: t('tenMeterShuttleRunPlaceholder'),
trigger: 'blur',
},
],
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editPhysicalTest : addPhysicalTest
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data)
.then((res) => {
loading.value = false
showDialog.value = false
emit('complete')
})
.catch((err) => {
loading.value = false
})
}
})
}
//
const resourceIdList = ref([] as any[])
const setResourceIdList = async () => {
resourceIdList.value = await (await getWithCustomerResourcesList({})).data
}
setResourceIdList()
const studentIdList = ref([] as any[])
const setStudentIdList = async () => {
studentIdList.value = await (await getWithStudentList({})).data
}
setStudentIdList()
const coachIdList = ref([] as any[])
const setCoachIdList = async () => {
coachIdList.value = await (await getWithPersonnelList({})).data
}
setCoachIdList()
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
Object.assign(formData, row)
// if(row){
// const data = await (await getPhysicalTestInfo(row.id)).data
// if (data) Object.keys(formData).forEach((key: string) => {
// if (data[key] != undefined) formData[key] = data[key]
// })
// }
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (
value &&
!/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
value
)
) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData,
})
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import {
addPhysicalTest,
editPhysicalTest,
getPhysicalTestInfo,
getWithCustomerResourcesList,
getWithStudentList,
getWithPersonnelList,
} from '@/app/api/physical_test'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
resource_id: '',
student_id: '',
height: '',
weight: '',
// coach_id: '',
seated_forward_bend: '',
sit_ups: '',
push_ups: '',
flamingo_balance: '',
thirty_sec_jump: '',
standing_long_jump: '',
agility_run: '',
balance_beam: '',
tennis_throw: '',
ten_meter_shuttle_run: '',
}
const formData : Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
resource_id: [
{ required: true, message: t('resourceIdPlaceholder'), trigger: 'blur' },
],
// student_id: [
// { required: true, message: t('studentIdPlaceholder'), trigger: 'blur' },
// ],
height: [
{ required: true, message: t('heightPlaceholder'), trigger: 'blur' },
],
weight: [
{ required: true, message: t('weightPlaceholder'), trigger: 'blur' },
],
// coach_id: [
// { required: true, message: t('coachIdPlaceholder'), trigger: 'blur' },
// ],
seated_forward_bend: [
{
required: true,
message: t('seatedForwardBendPlaceholder'),
trigger: 'blur',
},
],
sit_ups: [
{ required: true, message: t('sitUpsPlaceholder'), trigger: 'blur' },
],
push_ups: [
{ required: true, message: t('pushUpsPlaceholder'), trigger: 'blur' },
],
flamingo_balance: [
{
required: true,
message: t('flamingoBalancePlaceholder'),
trigger: 'blur',
},
],
thirty_sec_jump: [
{
required: true,
message: t('thirtySecJumpPlaceholder'),
trigger: 'blur',
},
],
standing_long_jump: [
{
required: true,
message: t('standingLongJumpPlaceholder'),
trigger: 'blur',
},
],
agility_run: [
{ required: true, message: t('agilityRunPlaceholder'), trigger: 'blur' },
],
balance_beam: [
{ required: true, message: t('balanceBeamPlaceholder'), trigger: 'blur' },
],
tennis_throw: [
{ required: true, message: t('tennisThrowPlaceholder'), trigger: 'blur' },
],
ten_meter_shuttle_run: [
{
required: true,
message: t('tenMeterShuttleRunPlaceholder'),
trigger: 'blur',
},
],
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl : FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editPhysicalTest : addPhysicalTest
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data)
.then((res) => {
loading.value = false
showDialog.value = false
emit('complete')
})
.catch((err) => {
loading.value = false
})
}
})
}
//
const resourceIdList = ref([] as any[])
const setResourceIdList = async () => {
resourceIdList.value = await (await getWithCustomerResourcesList({})).data
}
setResourceIdList()
const studentIdList = ref([] as any[])
const setStudentIdList = async () => {
studentIdList.value = await (await getWithStudentList({})).data
}
setStudentIdList()
const coachIdList = ref([] as any[])
const setCoachIdList = async () => {
coachIdList.value = await (await getWithPersonnelList({})).data
}
setCoachIdList()
const setFormData = async (row : any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
Object.assign(formData, row)
// if(row){
// const data = await (await getPhysicalTestInfo(row.id)).data
// if (data) Object.keys(formData).forEach((key: string) => {
// if (data[key] != undefined) formData[key] = data[key]
// })
// }
loading.value = false
}
//
const mobileVerify = (rule : any, value : any, callback : any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule : any, value : any, callback : any) => {
if (
value &&
!/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
value
)
) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule : any, value : any, callback : any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule : any, value : any, callback : any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData,
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>

52
admin/src/app/views/scsjtj/components/BarChart.vue

@ -0,0 +1,52 @@
<template>
<div ref="chartRef" style="width: 100%; height: 300px;"></div>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import * as echarts from 'echarts'
const props = defineProps({
data: {
type: Array,
default: () => []
}
})
const chartRef = ref(null)
let chartInstance = null
const renderChart = () => {
if (!chartInstance) {
chartInstance = echarts.init(chartRef.value)
}
const option = {
xAxis: {
type: 'category',
data: props.data.map(item => item.name)
},
yAxis: {
type: 'value'
},
series: [
{
type: 'bar',
data: props.data.map(item => item.value),
itemStyle: {
color: '#3b82f6'
},
barWidth: '40%'
}
]
}
chartInstance.setOption(option)
}
onMounted(() => {
renderChart()
})
watch(() => props.data, renderChart, { deep: true })
</script>

17
admin/src/app/views/scsjtj/components/Card.vue

@ -0,0 +1,17 @@
<template>
<div class="bg-white rounded-lg shadow p-4 text-center">
<div class="text-sm text-gray-500 mb-1">{{ title }}</div>
<div :class="['text-2xl font-semibold', color]">{{ value }}</div>
</div>
</template>
<script setup>
defineProps({
title: String,
value: String,
color: {
type: String,
default: 'text-gray-800'
}
})
</script>

69
admin/src/app/views/scsjtj/components/PieChart.vue

@ -0,0 +1,69 @@
<template>
<div ref="chartRef" style="width: 100%; height: 300px;"></div>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import * as echarts from 'echarts'
const props = defineProps({
data: {
type: Array,
default: () => []
}
})
const chartRef = ref(null)
let chartInstance = null
const renderChart = () => {
if (!chartInstance) {
chartInstance = echarts.init(chartRef.value)
}
const option = {
tooltip: {
trigger: 'item'
},
legend: {
bottom: 10
},
series: [
{
name: '资源来源',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '16',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: props.data
}
]
}
chartInstance.setOption(option)
}
onMounted(() => {
renderChart()
})
watch(() => props.data, renderChart, { deep: true })
</script>

127
admin/src/app/views/scsjtj/scsjtj.vue

@ -0,0 +1,127 @@
<template>
<div class="main-container">
<el-card shadow="never" class="!border-none">
<template #header>
<span class="text-sm text-[#a19f98]">业绩统计</span>
</template>
<el-row :gutter="24">
<el-col :span="4">
<Card title="资源数量" :value="info.zysl" color="text-blue-600" />
</el-col>
<el-col :span="5">
<Card title="已沟通资源" :value="info.ygt" color="text-green-600" />
</el-col>
<el-col :span="5">
<Card title="未沟通资源" :value="info.wgt" color="text-orange-600" />
</el-col>
<el-col :span="5">
<Card title="市场人员数量" :value="info.scry" color="text-purple-600" />
</el-col>
<el-col :span="5">
<Card title="已核算绩效金额" :value="info.yhs" color="text-red-600" />
</el-col>
</el-row>
</el-card>
<el-row :gutter="15" class="mt-[15px]">
<el-col :span="24">
<el-card shadow="never" class="!border-none">
<div class="flex items-center space-x-4">
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
<el-button type="primary" @click="Init()">搜索</el-button>
<el-button @click="dateRange = []">重置</el-button>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="15" class="mt-[15px]">
<el-col :span="12">
<el-card shadow="never" class="!border-none">
<el-card shadow="hover">
<h3 class="text-md font-bold mb-2">市场人员业绩统计</h3>
<BarChart :data="barData" />
</el-card>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never" class="!border-none">
<el-card shadow="hover">
<h3 class="text-md font-bold mb-2">资源来源分布</h3>
<PieChart :data="pieData" />
</el-card>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref,reactive } from 'vue'
import { ElDatePicker, ElButton, ElCard } from 'element-plus'
import Card from './components/Card.vue'
import BarChart from './components/BarChart.vue'
import PieChart from './components/PieChart.vue'
import { getScsjtj } from '@/app/api/sys'
const dateRange = ref([])
const barData = ref([])
const pieData = ref([])
const info = reactive({
zysl: 0,
ygt: 0,
wgt: 0,
scry: 0,
yhs: 0
})
const Init = () => {
getScsjtj({'dateRange':dateRange.value})
.then((res) => {
console.log(res);
info.zysl = res.data.zysl
info.ygt = res.data.ygt
info.wgt = res.data.wgt
info.scry = res.data.scry
info.yhs = res.data.yhs
barData.value = res.data.barData
pieData.value = res.data.pieData
})
.catch(() => {
})
}
Init();
</script>
<style scoped>
</style>

28
admin/src/app/views/service/components/service-edit.vue

@ -14,7 +14,15 @@
</el-form-item>
<el-form-item :label="t('serviceType')" prop="service_type">
<el-input v-model="formData.service_type" clearable :placeholder="t('serviceTypePlaceholder')" class="input-width" />
<el-select class="input-width" v-model="formData.service_type" clearable :placeholder="t('serviceTypePlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in service_typeList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('executionRules')" prop="execution_rules">
@ -28,7 +36,7 @@
v-for="(item, index) in staff_reminderList"
:key="index"
:label="item.name"
:value="Number(item.value)"
:value="item.value"
/>
</el-select>
</el-form-item>
@ -40,7 +48,7 @@
v-for="(item, index) in customer_reminderList"
:key="index"
:label="item.name"
:value="Number(item.value)"
:value="item.value"
/>
</el-select>
</el-form-item>
@ -52,14 +60,14 @@
v-for="(item, index) in customer_confirmationList"
:key="index"
:label="item.name"
:value="Number(item.value)"
:value="item.value"
/>
</el-select>
</el-form-item>
<!-- <el-form-item :label="t('customerFeedback')" >
<el-form-item :label="t('customerFeedback')" >
<el-input v-model="formData.customer_feedback" clearable :placeholder="t('customerFeedbackPlaceholder')" class="input-width" />
</el-form-item> -->
</el-form-item>
<el-form-item :label="t('status')" prop="status">
<el-select class="input-width" v-model="formData.status" clearable :placeholder="t('statusPlaceholder')">
@ -109,7 +117,7 @@ const initialFormData = {
staff_reminder: '',
customer_reminder: '',
customer_confirmation: '',
// customer_feedback: '',
customer_feedback: '',
status: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
@ -200,6 +208,12 @@ const confirm = async (formEl: FormInstance | undefined) => {
}
//
let service_typeList = ref([])
const service_typeDictList = async () => {
service_typeList.value = await (await useDictionary('service_type')).data.dictionary
}
service_typeDictList();
watch(() => service_typeList.value, () => { formData.service_type = service_typeList.value[0].value })
let staff_reminderList = ref([])
const staff_reminderDictList = async () => {
staff_reminderList.value = await (await useDictionary('global_true_or_false')).data.dictionary

25
admin/src/app/views/service/service.vue

@ -14,10 +14,20 @@
<el-form-item :label="t('serviceName')" prop="service_name">
<el-input v-model="serviceTable.searchParam.service_name" :placeholder="t('serviceNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('serviceType')" prop="service_type">
<el-input v-model="serviceTable.searchParam.service_type" :placeholder="t('serviceTypePlaceholder')" />
<el-select class="w-[280px]" v-model="serviceTable.searchParam.service_type" clearable :placeholder="t('serviceTypePlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in service_typeList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('status')" prop="status">
<el-select class="w-[280px]" v-model="serviceTable.searchParam.status" clearable :placeholder="t('statusPlaceholder')">
<el-option label="全部" value=""></el-option>
@ -46,7 +56,13 @@
<el-table-column prop="description" :label="t('description')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="service_type" :label="t('serviceType')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('serviceType')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in service_typeList">
<div v-if="item.value == row.service_type">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="customer_feedback" :label="t('customerFeedback')" min-width="120" :show-overflow-tooltip="true"/>
@ -109,6 +125,11 @@ const searchFormRef = ref<FormInstance>()
const selectData = ref<any[]>([])
//
const service_typeList = ref([] as any[])
const service_typeDictList = async () => {
service_typeList.value = await (await useDictionary('service_type')).data.dictionary
}
service_typeDictList();
const staff_reminderList = ref([] as any[])
const staff_reminderDictList = async () => {
staff_reminderList.value = await (await useDictionary('global_true_or_false')).data.dictionary

1
admin/src/app/views/student/student.vue

@ -169,6 +169,7 @@ let studentTable = reactive({
"contact_phone":"",
"created_at":[],
"member_label":'',
"class_id": route.query.class_id ?? ''
}
})

2
admin/src/app/views/venue/venue.vue

@ -118,7 +118,7 @@
<span>{{ !venueTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column
prop="campus_id_name"
prop="campus.campus_name"
:label="t('campusId')"
min-width="120"
:show-overflow-tooltip="true"

5
niucloud/app/adminapi/controller/campus/Campus.php

@ -89,9 +89,8 @@ class Campus extends BaseAdminController
* @return \think\Response
*/
public function del(int $id){
(new CampusService())->del($id);
return success('DELETE_SUCCESS');
return (new CampusService())->del($id);
}
}

4
niucloud/app/adminapi/controller/classroom/Classroom.php

@ -102,8 +102,8 @@ class Classroom extends BaseAdminController
*/
public function del(int $id)
{
(new ClassroomService())->del($id);
return success('DELETE_SUCCESS');
return (new ClassroomService())->del($id);
}

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

@ -154,6 +154,7 @@ class CustomerResources extends BaseAdminController
{
$data = $this->request->params([
["role_id", ""],
["dept_id",""]
]);
return success((new CustomerResourcesService())->getPersonnelAll($data));

6
niucloud/app/adminapi/controller/market_performance/MarketPerformance.php

@ -29,9 +29,9 @@ class MarketPerformance extends BaseAdminController
public function lists(){
$data = $this->request->params([
["campus_id",""],
["performance_amount",""]
["performance_amount",""],
["created_at",["",""]]
]);
return success((new MarketPerformanceService())->getPage($data));
}
@ -87,7 +87,7 @@ class MarketPerformance extends BaseAdminController
return success('DELETE_SUCCESS');
}
public function getPersonnelAll(){
return success(( new MarketPerformanceService())->getPersonnelAll());
}

39
niucloud/app/adminapi/controller/person_course_schedule/PersonCourseSchedule.php

@ -28,11 +28,9 @@ class PersonCourseSchedule extends BaseAdminController
*/
public function lists(){
$data = $this->request->params([
["person_id",""],
["person_type",""],
["schedule_id",""],
["course_date",""],
["time_slot",""]
["name",""],
["phone_number",""],
["campus_name",""]
]);
return success((new PersonCourseScheduleService())->getPage($data));
}
@ -52,9 +50,12 @@ class PersonCourseSchedule extends BaseAdminController
*/
public function add(){
$data = $this->request->params([
["resources_id",0],
["person_id",0],
["person_type",""],
["schedule_id",0],
["schedule_id",0]
["course_date","2025-05-29 17:03:27"],
["time_slot",""],
]);
$this->validate($data, 'app\validate\person_course_schedule\PersonCourseSchedule.add');
$id = (new PersonCourseScheduleService())->add($data);
@ -68,8 +69,11 @@ class PersonCourseSchedule extends BaseAdminController
*/
public function edit(int $id){
$data = $this->request->params([
["resources_id",0],
["schedule_id",0]
["person_id",0],
["person_type",""],
["schedule_id",0],
["course_date","2025-05-29 17:03:27"],
["time_slot",""],
]);
$this->validate($data, 'app\validate\person_course_schedule\PersonCourseSchedule.edit');
@ -84,13 +88,18 @@ class PersonCourseSchedule extends BaseAdminController
*/
public function del(int $id){
(new PersonCourseScheduleService())->del($id);
return success('DELETE_SUCCESS');
return success('请假成功');
}
/**
* 获取试课人员
*/
public function getTryCoursePerson($schedule_id){
return success((new PersonCourseScheduleService())->getTryCoursePerson($schedule_id));
public function xk(int $id){
(new PersonCourseScheduleService())->xk($id);
return success('销课成功');
}
public function getCustomerResourcesAll(){
return success(( new PersonCourseScheduleService())->getCustomerResourcesAll());
}
}

1
niucloud/app/adminapi/controller/student/Student.php

@ -34,6 +34,7 @@ class Student extends BaseAdminController
["contact_phone",""],
["created_at",["",""]],
['member_label', 0],
["class_id",""]
]);
return success((new StudentService())->getPage($data));
}

15
niucloud/app/adminapi/controller/sys/System.php

@ -152,12 +152,6 @@ class System extends BaseAdminController
}
public function home(){
// $data = $this->request->params([
// ['start_date', date('Y-m-d', strtotime('-6 day')) ],
// ['end_date', date('Y-m-d', strtotime('+1 day'))],
// ''
// ]);
$data = $this->request->params([
['date', 'week'],
]);
@ -166,4 +160,13 @@ class System extends BaseAdminController
}
public function scsjtj(){
$data = $this->request->params([
['dateRange', []],
]);
return success(data: (new SystemService())->scsjtj($data));
}
}

1
niucloud/app/adminapi/route/market_performance.php

@ -14,6 +14,7 @@ use think\facade\Route;
use app\adminapi\middleware\AdminCheckRole;
use app\adminapi\middleware\AdminCheckToken;
use app\adminapi\middleware\AdminLog;
// USER_CODE_BEGIN -- market_performance
Route::group('market_performance', function () {

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

@ -14,6 +14,7 @@ use think\facade\Route;
use app\adminapi\middleware\AdminCheckRole;
use app\adminapi\middleware\AdminCheckToken;
use app\adminapi\middleware\AdminLog;
// USER_CODE_BEGIN -- person_course_schedule
Route::group('person_course_schedule', function () {
@ -28,8 +29,11 @@ Route::group('person_course_schedule', function () {
Route::put('person_course_schedule/:id', 'person_course_schedule.PersonCourseSchedule/edit');
//删除人员与课程安排关系
Route::delete('person_course_schedule/:id', 'person_course_schedule.PersonCourseSchedule/del');
//获取试课人员
Route::get('get_try_course_person/:schedule_id', 'person_course_schedule.PersonCourseSchedule/getTryCoursePerson');
Route::delete('xk/:id', 'person_course_schedule.PersonCourseSchedule/xk');
Route::get('customer_resources_all','person_course_schedule.PersonCourseSchedule/getCustomerResourcesAll');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,

1
niucloud/app/adminapi/route/service.php

@ -16,6 +16,7 @@ use app\adminapi\middleware\AdminCheckToken;
use app\adminapi\middleware\AdminLog;
// USER_CODE_BEGIN -- service
Route::group('service', function () {

3
niucloud/app/adminapi/route/sys.php

@ -340,6 +340,9 @@ Route::group('sys', function() {
Route::post('home', 'sys.System/home');
Route::post('scsjtj', 'sys.System/scsjtj');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,

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

@ -131,6 +131,9 @@ class CustomerResources extends BaseApiService
"distance" => $request->param('distance', ''),//距离
"communication" => $request->param('communication', ''),//沟通备注
"staff_id" => $request->param('staff_id', ''),//人员ID
"first_visit_status" => $request->param('first_visit_status', null),//一访情况
"second_visit_status" => $request->param('second_visit_status', null),//二访情况
];
foreach($customer_resources_data as $k=>$v){
@ -139,6 +142,10 @@ class CustomerResources extends BaseApiService
}
}
foreach($six_speed_data as $k=>$v){
// 排除 first_visit_status 和 second_visit_status 的必填校验
if (in_array($k, ['first_visit_status', 'second_visit_status'])) {
continue;
}
if(!isset($v) || $v === ''){
return fail("缺少必填项{$k}");
}

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

@ -15,6 +15,7 @@ use app\service\api\upload\Base64Service;
use app\service\api\upload\FetchService;
use app\service\api\upload\UploadService;
use core\base\BaseApiController;
use think\Request;
use think\Response;
class Upload extends BaseApiController
@ -24,12 +25,15 @@ class Upload extends BaseApiController
* 图片上传
* @return Response
*/
public function image(){
public function image(Request $request){
$extraData = $request->all();
$data = $this->request->params([
['file', 'file'],
]);
$upload_service = new UploadService();
return success($upload_service->image($data['file']));
return success($upload_service->image($data['file'],$extraData));
}
/**

2
niucloud/app/api/route/route.php

@ -201,7 +201,7 @@ Route::group(function () {
//需要token验证的
Route::group(function () {
//上传图片
//员工端-上传图片
Route::post('uploadImage', 'upload.Upload/image');
//员工端详情
Route::get('personnel/info', 'apiController.Personnel/info');

4
niucloud/app/model/chat_friends/ChatFriends.php

@ -80,8 +80,8 @@ class ChatFriends extends BaseModel
}
public function campus(){
return $this->hasOne(CustomerResources::class, 'id', 'customer_resources_id')->joinType('left')->withField('name,id')->bind(['customer_resources_id'=>'name']);
public function customer(){
return $this->hasOne(CustomerResources::class, 'id', 'customer_resources_id')->joinType('left')->withField('name,id')->bind(['customer_resources_id_name'=>'name']);
}
public function personnel(){

18
niucloud/app/model/market_performance/MarketPerformance.php

@ -70,6 +70,24 @@ class MarketPerformance extends BaseModel
}
}
/**
* 搜索器:市场绩效创建时间
* @param $value
* @param $data
*/
public function searchCreatedAtAttr($query, $value, $data)
{
$start = empty($value[0]) ? 0 : strtotime($value[0]);
$end = empty($value[1]) ? 0 : strtotime($value[1]);
if ($start > 0 && $end > 0) {
$query->where([["created_at", "between", [$start, $end]]]);
} else if ($start > 0 && $end == 0) {
$query->where([["created_at", ">=", $start]]);
} else if ($start == 0 && $end > 0) {
$query->where([["created_at", "<=", $end]]);
}
}

82
niucloud/app/model/person_course_schedule/PersonCourseSchedule.php

@ -11,14 +11,12 @@
namespace app\model\person_course_schedule;
use app\model\customer_resources\CustomerResources;
use app\model\personnel\Personnel;
use app\model\student\Student;
use core\base\BaseModel;
use think\model\concern\SoftDelete;
use think\model\relation\HasMany;
use think\model\relation\HasOne;
use app\model\customer_resources\CustomerResources;
/**
* 人员与课程安排关系模型
* Class PersonCourseSchedule
@ -26,6 +24,8 @@ use think\model\relation\HasOne;
*/
class PersonCourseSchedule extends BaseModel
{
/**
* 数据表主键
* @var string
@ -38,92 +38,26 @@ class PersonCourseSchedule extends BaseModel
*/
protected $name = 'person_course_schedule';
/**
* 搜索器:人员与课程安排关系关系编号
* @param $value
* @param $data
*/
public function searchIdAttr($query, $value, $data)
{
if ($value) {
$query->where("id", $value);
}
}
/**
* 搜索器:人员与课程安排关系人员或资源ID
* 搜索器:人员与课程安排关系资源
* @param $value
* @param $data
*/
public function searchPersonIdAttr($query, $value, $data)
{
if ($value) {
if ($value) {
$query->where("person_id", $value);
}
}
/**
* 搜索器:人员与课程安排关系人员类型: student-正式学员, customer_resource-客户资源
* @param $value
* @param $data
*/
public function searchPersonTypeAttr($query, $value, $data)
{
if ($value) {
$query->where("person_type", $value);
}
}
/**
* 搜索器:人员与课程安排关系课程安排ID
* @param $value
* @param $data
*/
public function searchScheduleIdAttr($query, $value, $data)
{
if ($value) {
$query->where("schedule_id", $value);
}
}
/**
* 搜索器:人员与课程安排关系上课日期
* @param $value
* @param $data
*/
public function searchCourseDateAttr($query, $value, $data)
{
if ($value) {
$query->where("course_date", $value);
}
}
/**
* 搜索器:人员与课程安排关系上课时段
* @param $value
* @param $data
*/
public function searchTimeSlotAttr($query, $value, $data)
{
if ($value) {
$query->where("time_slot", $value);
}
}
public function person()
{
return $this->hasOne(Personnel::class, 'id', 'person_id');
}
public function student()
{
return $this->hasOne(Student::class, 'id', 'student_id');
}
public function resources()
{
return $this->hasOne(CustomerResources::class, 'id', 'resources_id');
public function customerResources(){
return $this->hasOne(CustomerResources::class, 'id', 'person_id')->joinType('left')->withField('name,id')->bind(['person_id_name'=>'name']);
}
}

8
niucloud/app/service/admin/campus/CampusService.php

@ -13,6 +13,7 @@ namespace app\service\admin\campus;
use app\model\campus\Campus;
use app\model\student\Student;
use core\base\BaseAdminService;
@ -94,13 +95,16 @@ class CampusService extends BaseAdminService
/**
* 删除校区
* @param int $id
* @return bool
*/
public function del(int $id)
{
$student = new Student();
if($student->where(['campus_id' => $id])->find()){
return fail("校区下有学员禁止删除");
}
$model = $this->model->where([['id', '=', $id]])->find();
$res = $model->delete();
return $res;
return success('DELETE_SUCCESS');
}

8
niucloud/app/service/admin/classroom/ClassroomService.php

@ -17,6 +17,7 @@ use app\model\course_schedule\CourseSchedule;
use app\model\personnel\Personnel;
use app\model\rel\ClassPersonnelRel;
use app\model\student\Student;
use core\base\BaseAdminService;
@ -90,13 +91,16 @@ class ClassroomService extends BaseAdminService
/**
* 删除场地管理
* @param int $id
* @return bool
*/
public function del(int $id)
{
$student = new Student();
if($student->where(['class_id' => $id])->find()){
return fail("班级下有学员禁止删除");
}
$model = $this->model->where([['id', '=', $id]])->find();
$res = $model->delete();
return $res;
return success('DELETE_SUCCESS');
}

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

@ -136,7 +136,7 @@ class CustomerResourcesService extends BaseAdminService
$data['consultant'] = $personnel->where(['sys_user_id' => $this->uid])->value("id");
if (!$data['consultant']) {
return fail("操作失败");
return fail("超级管理员不允许添加资源");
}
$sixSpeed = new SixSpeed();
@ -299,15 +299,20 @@ class CustomerResourcesService extends BaseAdminService
public function getPersonnelAll($data)
{
$school_campus_person_role = new CampusPersonRole();
$personnelModel = new Personnel();
$where = [];
if ($data['role_id']) {
$where[] = ['b.role_id', '=', $data['role_id']];
$where[] = ['a.role_id', '=', $data['role_id']];
}
return $personnelModel
if ($data['dept_id']) {
$where[] = ['a.dept_id', '=', $data['dept_id']];
}
return $school_campus_person_role
->alias("a")
->join(['school_campus_person_role' => 'b'], 'a.id = b.person_id', 'left')
->field("a.*")
->join(['school_personnel' => 'b'], 'a.person_id = b.id', 'left')
->field("b.*")
->where($where)->select()->toArray();
}

4
niucloud/app/service/admin/market_performance/MarketPerformanceService.php

@ -41,7 +41,7 @@ class MarketPerformanceService extends BaseAdminService
$field = 'id,personnel_id,campus_id,performance_amount,resource_count,performance_date,performance_config,performance_algorithm,status,created_at,updated_at';
$order = 'id desc';
$search_model = $this->model->where(get_campus_where($this->uid))->withSearch(["campus_id","performance_amount"], $where)->with(['personnel','campus'])->field($field)->order($order);
$search_model = $this->model->withSearch(["campus_id","performance_amount","created_at"], $where)->with(['personnel','campus'])->field($field)->order($order);
$list = $this->pageQuery($search_model);
return $list;
}
@ -96,7 +96,7 @@ class MarketPerformanceService extends BaseAdminService
return $res;
}
public function getPersonnelAll(){
$personnelModel = new Personnel();
return $personnelModel->select()->toArray();

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

@ -11,6 +11,7 @@
namespace app\service\admin\person_course_schedule;
use app\model\course\Course;
use app\model\course_schedule\CourseSchedule;
use app\model\customer_resources\CustomerResources;
use app\model\person_course_schedule\PersonCourseSchedule;
@ -38,14 +39,37 @@ class PersonCourseScheduleService extends BaseAdminService
* @param array $where
* @return array
*/
public function getPage(array $where = [])
public function getPage(array $data = [])
{
$field = 'id,person_id,person_type,schedule_id,course_date,time_slot,created_at,updated_at';
$order = 'id desc';
$order = 'a.id desc';
$where = [];
if($data['name']){
$where[] = ['b.name','=',$data['name']];
}
if($data['phone_number']){
$where[] = ['b.phone_number','=',$data['phone_number']];
}
$search_model = $this->model->withSearch(["id", "person_id", "person_type", "schedule_id", "course_date", "time_slot"], $where)->field($field)->order($order);
$list = $this->pageQuery($search_model);
return $list;
if($data['campus_name']){
$where[] = ['c.campus_name','=',$data['campus_name']];
}
$search_model = $this->model
->alias("a")
->join(['school_customer_resources' => 'b'],'a.person_id = b.id','left')
->join(['school_campus'=>'c'],'b.campus = c.id','left')
->where($where)
->field('a.*,b.name')
->order($order);
return $this->pageQuery($search_model, function ($item, $key) {
// $course = new Course();
$course_schedule = new CourseSchedule();
$course_type = $course_schedule
->alias("a")
->join(['school_course' => 'b'],'a.course_id = b.id','left')
->value("b.course_type");
$item['course_type'] = $course_type;
});
}
/**
@ -55,9 +79,9 @@ class PersonCourseScheduleService extends BaseAdminService
*/
public function getInfo(int $id)
{
$field = 'id,person_id,person_type,schedule_id,course_date,time_slot,created_at,updated_at';
$field = 'id,person_id,person_type,schedule_id,course_date,time_slot,created_at,updated_at,deleted_at';
$info = $this->model->field($field)->where([['id', "=", $id]])->findOrEmpty()->toArray();
$info = $this->model->field($field)->where([['id', "=", $id]])->with(['customerResources'])->findOrEmpty()->toArray();
return $info;
}
@ -194,4 +218,15 @@ class PersonCourseScheduleService extends BaseAdminService
}
return $data;
}
public function xk(int $id){
$model = $this->model->where([['id', '=', $id]])->find();
$res = $model->delete();
return $res;
}
public function getCustomerResourcesAll(){
$customerResourcesModel = new CustomerResources();
return $customerResourcesModel->select()->toArray();
}
}

2
niucloud/app/service/admin/student/StudentService.php

@ -45,7 +45,7 @@ class StudentService extends BaseAdminService
$field = 'id,user_id,campus_id,class_id,name,gender,age,birthday,member_label,emergency_contact,contact_phone,note,status,created_at,updated_at,deleted_at';
$order = 'id desc';
$search_model = $this->model->withSearch(["campus_id", "name", "emergency_contact", "contact_phone", "created_at", "member_label"], $where)->with(['customerResources', 'campus', 'classGrade'])->field($field)->order($order);
$search_model = $this->model->withSearch(["campus_id", "name", "emergency_contact", "contact_phone", "created_at", "member_label","class_id"], $where)->with(['customerResources', 'campus', 'classGrade'])->field($field)->order($order);
return $this->pageQuery($search_model, function ($item, $key) {
$item = $this->makeUp($item);
});

57
niucloud/app/service/admin/sys/SystemService.php

@ -14,7 +14,10 @@ namespace app\service\admin\sys;
use addon\shop\app\model\ShopStat;
use app\job\sys\CheckJob;
use app\model\campus\Campus;
use app\model\campus_person_role\CampusPersonRole;
use app\model\communication_records\CommunicationRecords;
use app\model\customer_resources\CustomerResources;
use app\model\market_performance\MarketPerformance;
use app\model\personnel\Personnel;
use app\model\student\Student;
use app\model\sys\SysConfig;
@ -285,4 +288,58 @@ class SystemService extends BaseAdminService
return $data;
}
public function scsjtj(array $row){
$customerResources = new CustomerResources();
$campus_person_role = new CampusPersonRole();
$communication_records = new CommunicationRecords();
$market_performance = new MarketPerformance();
$per = new Personnel();
$data['zysl'] = $customerResources->count();
$data['ygt'] = 0;
$data['wgt'] = 0;
$list = $customerResources->select();
foreach ($list as $k => $v) {
if($communication_records->where(['resource_id' => $v['id']])->find()){
$data['ygt']++;
}else{
$data['wgt']++;
}
}
$data['scry'] = $campus_person_role->where(['dept_id' => 1])->count();
$start = date('Y-m-01');
$end = date('Y-m-t');
$data['yhs'] = $market_performance->whereBetween('performance_date', [$start, $end])->Sum("performance_amount");
$data['barData'] = [];
$where = [];
$c_where = [];
if(!empty($row['dateRange'])){
$where[] = ['performance_date','>=',$row['dateRange'][0]];
$where[] = ['performance_date','<=',$row['dateRange'][1]];
$c_where[] = ['create_date','>=',$row['dateRange'][0]];
$c_where[] = ['create_date','<=',$row['dateRange'][1]];
}
$sc_list = $campus_person_role->where(['dept_id' => 1])->select()->toArray();
foreach ($sc_list as $k => $v) {
$data['barData'][] = [
'name' => $per->where(['id' => $v['person_id']])->value('name'),
'value' => $market_performance->where(['personnel_id' => $v['person_id']])->where($where)->Sum("performance_amount")
];
}
$arr = [0=>'未知',1=>'线上',2=>'地推',3=>'转介绍',4=>'活动',5=>'内部员工'];
$data['pieData'] = [];
foreach ($arr as $k => $v) {
$data['pieData'][] = [
'name' => $v,
'value' => $customerResources->where(['source_channel' => $k])->where($c_where)->count()
];
}
return $data;
}
}

7
niucloud/app/service/api/apiService/ChatService.php

@ -48,7 +48,12 @@ class ChatService extends BaseApiService
$model = $model->where('customer_resources_id', $where['customer_resources_id']);
}
$data = $model->paginate([
$data = $model
->with([
'personnel',
'customer',
])
->paginate([
'list_rows' => $limit,
'page' => $page,
])->toArray();

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

@ -15,6 +15,7 @@ use app\model\campus_person_role\CampusPersonRole;
use app\model\customer_resource_changes\CustomerResourceChanges;
use app\model\customer_resources\CustomerResources;
use app\model\dict\Dict;
use app\model\member\Member;
use app\model\personnel\Personnel;
use app\model\resource_sharing\ResourceSharing;
use app\model\six_speed\SixSpeed;
@ -122,10 +123,47 @@ class CustomerResourcesService extends BaseApiService
//开启事物
Db::startTrans();
try {
$customer_resources = CustomerResources::where('id', $where['id'])->find();
$six_speed = SixSpeed::where('resource_id', $where['id'])->find();
if ($customer_resources) {
$customer_resources = $customer_resources->toArray();
if(!$customer_resources['member_id'] && $six_speed){
//新数据存在一访问 或者旧数据存在一访的情况 && 这用户没注册过member账号的情况下才给他创建member账号
if(!empty($six_speed_data['first_visit_status']) || $six_speed['first_visit_status']){
$sex = 0;
switch ($customer_resources_data['gender']) {
case 'male'://男
$sex = 1;
break;
case 'female'://女
$sex = 2;
break;
default://其他
$sex = 0;
break;
}
$password = create_password($customer_resources_data['phone_number']);//创建密码
//给用户创建member账号
$member_id = Member::insertGetId([
'username'=>$customer_resources_data['phone_number'],//会员用户名
'mobile'=>$customer_resources_data['phone_number'],//手机号
'password'=>$password,//会员密码
'nickname'=>$customer_resources_data['name'],//会员昵称
'sex'=>$sex,//性别 0保密 1男 2女
'member_time'=>time(),//成为会员时间
]);
if($member_id){
$customer_resources_data['member_id'] = $member_id;
}else{
Db::rollback();
$res['msg'] = '创建用户账号失败';
return $res;
}
}
}
}
$update_1 = CustomerResources::where('id', $where['id'])->update($customer_resources_data);//客户资源表
if (!$update_1) {
@ -157,7 +195,6 @@ class CustomerResourcesService extends BaseApiService
$six_speed_data['resource_id'] = $where['id'];
//查六要素是否存在
$six_speed = SixSpeed::where('resource_id', $where['id'])->find();
if ($six_speed) {
$six_speed = $six_speed->toArray();
//更新六要素

6
niucloud/app/service/api/apiService/ResourceSharingService.php

@ -115,15 +115,19 @@ class ResourceSharingService extends BaseApiService
]);
}
])->field($field)->find();
if($data){
$data = $data->toArray();
}
if (!empty($data['customerResource'])) {
$data['customerResource']['cj_count'] = OrderTable::where('resource_id', $data['customerResource']['id'])
->where('order_status', 'paid')
->count();//成交次数
}
// dd(123123,$data);
if ($data) {
$res['code'] = 1;
$res['msg'] = '操作成功';
$res['data'] = $data->toArray();
$res['data'] = $data;
} else {
$res['code'] = 0;

4
niucloud/app/service/api/upload/UploadService.php

@ -34,9 +34,9 @@ class UploadService extends BaseApiService
* @return array
* @throws Exception
*/
public function image($file)
public function image($file,array $extraData = [])
{
$dir = $this->root_path . '/' . 'image' . '/' . date('Ym') . '/' . date('d');
$dir = $this->root_path . '/' . 'image' . '/' . date('Ym') . '/' . date('d');//打印结果 例如=file/image/202505/29
$core_upload_service = new CoreUploadService();
return $core_upload_service->image($file, $dir, $this->cate_id);
}

18
niucloud/app/validate/person_course_schedule/PersonCourseSchedule.php

@ -20,18 +20,24 @@ class PersonCourseSchedule extends BaseValidate
{
protected $rule = [
'resources_id' => 'require',
'schedule_id' => 'require'
'person_id' => 'require',
'person_type' => 'require',
'schedule_id' => 'require',
'course_date' => 'require',
'time_slot' => 'require',
];
protected $message = [
'resources_id.require' => ['common_validate.require', ['person_id']],
'schedule_id.require' => ['common_validate.require', ['schedule_id']]
'person_id.require' => ['common_validate.require', ['person_id']],
'person_type.require' => ['common_validate.require', ['person_type']],
'schedule_id.require' => ['common_validate.require', ['schedule_id']],
'course_date.require' => ['common_validate.require', ['course_date']],
'time_slot.require' => ['common_validate.require', ['time_slot']],
];
protected $scene = [
"add" => ['resources_id', 'schedule_id'],
"edit" => ['resources_id', 'schedule_id']
"add" => ['person_id', 'person_type', 'schedule_id', 'course_date', 'time_slot'],
"edit" => ['person_id', 'person_type', 'schedule_id', 'course_date', 'time_slot']
];
}

Loading…
Cancel
Save