Browse Source

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	niucloud/app/service/admin/pay/PayService.php
master
王泽彦 9 months ago
parent
commit
0932304bf5
  1. 23
      admin/src/app/views/classroom/components/classroom-edit.vue
  2. 2
      admin/src/app/views/customer_resources/customer_resources.vue
  3. 400
      admin/src/views/personnel/personnel_approval_demo.vue
  4. 2
      niucloud/app/adminapi/controller/classroom/Classroom.php
  5. 63
      niucloud/app/common.php
  6. 4
      niucloud/app/service/admin/classroom/ClassroomService.php
  7. 2
      niucloud/app/service/admin/customer_resources/CustomerResourcesService.php
  8. 15
      niucloud/app/service/admin/order_table/OrderTableService.php
  9. 26
      niucloud/app/service/admin/pay/PayService.php
  10. 5
      niucloud/app/service/api/pay/PayService.php

23
admin/src/app/views/classroom/components/classroom-edit.vue

@ -52,7 +52,7 @@
v-for="(item, index) in headCoachList" v-for="(item, index) in headCoachList"
:key="index" :key="index"
:label="item['name']" :label="item['name']"
:value="item['id']" :value="String(item['id'])"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -96,10 +96,28 @@
v-for="(item, index) in assistantCoachList" v-for="(item, index) in assistantCoachList"
:key="index" :key="index"
:label="item['name']" :label="item['name']"
:value="item['id']" :value="String(item['id'])"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="教务" prop="educational_id">
<el-select
class="input-width"
v-model="formData.educational_id"
clearable
placeholder="请选择教务"
>
<el-option label="请选择教务" value=""></el-option>
<el-option
v-for="(item, index) in headCoachList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('status')" prop="status"> <el-form-item :label="t('status')" prop="status">
<el-radio-group <el-radio-group
@ -176,6 +194,7 @@ const initialFormData = {
age_group: '', age_group: '',
class_type: '', class_type: '',
assistant_coach: '', assistant_coach: '',
educational_id:'',
status: '', status: '',
sort_order: '', sort_order: '',
remarks: '', remarks: '',

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

@ -335,7 +335,7 @@
const addOrder = (row : any) => { const addOrder = (row : any) => {
console.log(row); console.log(row);
editOrderTableDialog.value.setFormData(row) editOrderTableDialog.value.setFormData({'resource_id' : row.id})
editOrderTableDialog.value.showDialog = true editOrderTableDialog.value.showDialog = true
} }

400
admin/src/views/personnel/personnel_approval_demo.vue

@ -1,400 +0,0 @@
<template>
<div class="personnel-approval-demo">
<el-card class="demo-card" shadow="hover">
<template #header>
<div class="card-header">
<h3>人员添加审批功能演示</h3>
<p class="desc">该功能展示如何将人员添加接入审批流程</p>
</div>
</template>
<!-- 审批配置选择 -->
<div class="section">
<h4>第一步选择审批配置</h4>
<el-form :model="form" label-width="120px" size="default">
<el-form-item label="是否使用审批:">
<el-switch
v-model="form.useApproval"
active-text="启用审批流程"
inactive-text="直接添加"
@change="onApprovalToggle">
</el-switch>
</el-form-item>
<el-form-item
v-if="form.useApproval"
label="审批配置:"
required>
<el-select
v-model="form.approvalConfigId"
placeholder="请选择审批配置"
:loading="configLoading"
clearable>
<el-option
v-for="config in approvalConfigs"
:key="config.id"
:label="config.config_name"
:value="config.id">
<span>{{ config.config_name }}</span>
<span style="float: right; color: #8492a6;">{{ config.description }}</span>
</el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<!-- 人员信息填写 -->
<div class="section">
<h4>第二步填写人员信息</h4>
<el-form :model="personnelForm" :rules="rules" ref="personnelFormRef" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="姓名:" prop="name">
<el-input v-model="personnelForm.name" placeholder="请输入姓名"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别:" prop="gender">
<el-radio-group v-model="personnelForm.gender">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手机号:" prop="phone">
<el-input v-model="personnelForm.phone" placeholder="请输入手机号"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态:" prop="status">
<el-select v-model="personnelForm.status" placeholder="请选择状态">
<el-option label="正常" :value="1"></el-option>
<el-option label="禁用" :value="0"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="家庭住址:">
<el-input v-model="personnelForm.address" placeholder="请输入家庭住址"></el-input>
</el-form-item>
<el-form-item label="学历:">
<el-select v-model="personnelForm.education" placeholder="请选择学历">
<el-option label="高中及以下" value="高中及以下"></el-option>
<el-option label="大专" value="大专"></el-option>
<el-option label="本科" value="本科"></el-option>
<el-option label="硕士" value="硕士"></el-option>
<el-option label="博士" value="博士"></el-option>
</el-select>
</el-form-item>
<el-form-item label="个人简介:">
<el-input
v-model="personnelForm.profile"
type="textarea"
:rows="3"
placeholder="请输入个人简介">
</el-input>
</el-form-item>
<el-form-item label="是否系统用户:">
<el-switch
v-model="personnelForm.isSysUser"
active-text="是"
inactive-text="否">
</el-switch>
</el-form-item>
</el-form>
</div>
<!-- 提交按钮 -->
<div class="section">
<h4>第三步提交申请</h4>
<el-button
type="primary"
size="large"
:loading="submitLoading"
@click="handleSubmit">
{{ form.useApproval ? '提交审批申请' : '直接添加人员' }}
</el-button>
<el-button
size="large"
@click="handleReset">
重置表单
</el-button>
</div>
<!-- 结果展示 -->
<div v-if="result" class="section result-section">
<h4>处理结果</h4>
<el-alert
:title="result.title"
:description="result.description"
:type="result.type"
show-icon
:closable="false">
</el-alert>
</div>
</el-card>
<!-- 审批流程状态展示 -->
<el-card v-if="showApprovalStatus" class="approval-status-card" shadow="hover">
<template #header>
<h3>审批流程状态</h3>
</template>
<div class="approval-flow">
<el-steps :active="currentStep" finish-status="success" align-center>
<el-step
v-for="(step, index) in approvalSteps"
:key="index"
:title="step.title"
:description="step.description">
</el-step>
</el-steps>
</div>
</el-card>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { apiRequest } from '@/utils/request'
//
const form = reactive({
useApproval: false,
approvalConfigId: null
})
const personnelForm = reactive({
name: '',
gender: 0,
phone: '',
address: '',
education: '',
profile: '',
status: 1,
isSysUser: false,
info: {}
})
const approvalConfigs = ref([])
const configLoading = ref(false)
const submitLoading = ref(false)
const result = ref(null)
const showApprovalStatus = ref(false)
const currentStep = ref(0)
const approvalSteps = ref([])
//
const rules = {
name: [
{ required: true, message: '请输入姓名', trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
],
gender: [
{ required: true, message: '请选择性别', trigger: 'change' }
],
status: [
{ required: true, message: '请选择状态', trigger: 'change' }
]
}
const personnelFormRef = ref()
//
const loadApprovalConfigs = async () => {
configLoading.value = true
try {
const response = await apiRequest({
url: '/adminapi/personnel/approval-configs',
method: 'GET'
})
if (response.data.code === 1) {
approvalConfigs.value = response.data.data.list || []
}
} catch (error) {
ElMessage.error('获取审批配置失败')
} finally {
configLoading.value = false
}
}
//
const onApprovalToggle = (value) => {
if (value && approvalConfigs.value.length === 0) {
loadApprovalConfigs()
}
if (!value) {
form.approvalConfigId = null
}
}
//
const handleSubmit = async () => {
//
const valid = await personnelFormRef.value.validate()
if (!valid) {
return
}
// 使
if (form.useApproval && !form.approvalConfigId) {
ElMessage.warning('请选择审批配置')
return
}
submitLoading.value = true
try {
const submitData = {
...personnelForm,
use_approval: form.useApproval ? 1 : 0,
approval_config_id: form.approvalConfigId || 0
}
const response = await apiRequest({
url: '/adminapi/personnel/personnel',
method: 'POST',
data: submitData
})
if (response.data.code === 1) {
if (form.useApproval) {
result.value = {
title: '审批申请提交成功',
description: `已成功提交人员添加审批申请,流程ID: ${response.data.data.process_id},请等待审批人处理。`,
type: 'success'
}
showApprovalDemo()
} else {
result.value = {
title: '人员添加成功',
description: `人员 ${personnelForm.name} 添加成功,ID: ${response.data.data.id}`,
type: 'success'
}
}
} else {
result.value = {
title: '提交失败',
description: response.data.msg || '操作失败,请重试',
type: 'error'
}
}
} catch (error) {
result.value = {
title: '提交失败',
description: '网络错误,请稍后重试',
type: 'error'
}
} finally {
submitLoading.value = false
}
}
//
const showApprovalDemo = () => {
showApprovalStatus.value = true
approvalSteps.value = [
{ title: '提交申请', description: '用户提交人员添加申请' },
{ title: '部门审批', description: '部门负责人审批' },
{ title: 'HR审批', description: 'HR部门审批' },
{ title: '完成', description: '审批完成,创建人员记录' }
]
currentStep.value = 1 //
}
//
const handleReset = () => {
personnelFormRef.value.resetFields()
form.useApproval = false
form.approvalConfigId = null
result.value = null
showApprovalStatus.value = false
}
//
onMounted(() => {
//
personnelForm.name = '张三'
personnelForm.phone = '13800138000'
personnelForm.address = '北京市朝阳区'
personnelForm.education = '本科'
personnelForm.profile = '具有丰富的教学经验,专业技能扎实。'
})
</script>
<style scoped>
.personnel-approval-demo {
padding: 20px;
}
.demo-card {
margin-bottom: 20px;
}
.card-header {
text-align: center;
}
.card-header h3 {
margin: 0 0 10px 0;
color: #303133;
}
.card-header .desc {
margin: 0;
color: #909399;
font-size: 14px;
}
.section {
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #ebeef5;
}
.section:last-child {
border-bottom: none;
margin-bottom: 0;
}
.section h4 {
margin: 0 0 20px 0;
color: #606266;
font-size: 16px;
font-weight: 600;
}
.result-section {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
}
.approval-status-card {
margin-top: 20px;
}
.approval-flow {
padding: 20px 0;
}
:deep(.el-step__description) {
color: #909399;
font-size: 12px;
}
:deep(.el-alert__description) {
font-size: 14px;
line-height: 1.6;
}
</style>

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

@ -63,6 +63,7 @@ class Classroom extends BaseAdminController
["age_group", ""], ["age_group", ""],
["class_type", ""], ["class_type", ""],
["assistant_coach", ""], ["assistant_coach", ""],
["educational_id",""],
["status", ""], ["status", ""],
["sort_order", 0], ["sort_order", 0],
["remarks", ""] ["remarks", ""]
@ -86,6 +87,7 @@ class Classroom extends BaseAdminController
["age_group", ""], ["age_group", ""],
["class_type", ""], ["class_type", ""],
["assistant_coach", ""], ["assistant_coach", ""],
["educational_id",""],
["status", ""], ["status", ""],
["sort_order", 0], ["sort_order", 0],
["remarks", ""] ["remarks", ""]

63
niucloud/app/common.php

@ -1108,7 +1108,7 @@ function return_pay_config($campus_id, $order_id)
// 必填-商户公钥证书路径 // 必填-商户公钥证书路径
'mch_public_cert_path' => $pay_config['apiclient_key'], 'mch_public_cert_path' => $pay_config['apiclient_key'],
// 必填 // 必填
'notify_url' => 'https://zh.hnhbty.cn/api/pay/qrcodenotify/order_id/' . $order_id, 'notify_url' => 'https://api.hnhbty.cn/api/pay/qrcodenotify/order_id/' . $order_id,
// 选填-公众号 的 app_id // 选填-公众号 的 app_id
'mp_app_id' => $vx_config['app_id'], 'mp_app_id' => $vx_config['app_id'],
// 选填-小程序 的 app_id // 选填-小程序 的 app_id
@ -1362,3 +1362,64 @@ function get_staff_performance_total(int $staffId, string $performanceType = '',
} }
} }
function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
function getAccessToken() {
$appId = 'wxaee2df4a4b31df05';
$appSecret = '06284bac15b25775293690765a6be4d9';
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appId&secret=$appSecret";
$res = json_decode(httpGet($url));
$access_token = $res->access_token;
return $access_token;
}
//$touser 用户的openid
//$template_id 模板id
//$value 发送的 消息 数组
function sendMessage($touser,$template_id,$value) {
// 构建请求参数
$accessToken = getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" .$accessToken;
if($template_id == 'ogmlvTC-Q2gLMBbRHAUKCSWpwyQIOrLBA30HyAKkEXg'){
$data = [
'touser' => $touser,
'template_id' => $template_id,
'data' => [
'thing3' => ['value' => $value['thing3'], 'color' => '#173177'], //课程名称
'time4' => ['value' => $value['time4'], 'color' => '#173177'],//课程周期 例子 2023年10月11日~2023年11月30日
'character_string7' => ['value' => $value['character_string7'], 'color' => '#173177'],//课程数量
'character_string9' => ['value' => $value['character_string9'], 'color' => '#173177'],//课程码 课程金额
'time5' => ['value' => $value['time5'], 'color' => '#173177']//上课时间
],
'miniprogram' => [
"appid" => "wxaee2df4a4b31df05",
"pagepath" => $value['pagepath']
]
];
}
// 发送 POST 请求
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
}

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

@ -41,7 +41,7 @@ class ClassroomService extends BaseAdminService
*/ */
public function getPage(array $where = []) public function getPage(array $where = [])
{ {
$field = 'id,campus_id,campus_name,class_name,head_coach,age_group,class_type,assistant_coach,created_at,updated_at,deleted_at,status,sort_order,remarks'; $field = 'id,campus_id,campus_name,class_name,educational_id,head_coach,age_group,class_type,assistant_coach,created_at,updated_at,deleted_at,status,sort_order,remarks';
$order = 'id desc'; $order = 'id desc';
$search_model = $this->model->withSearch(["campus_id", "class_name", "head_coach", "class_type", "assistant_coach", "created_at", "status"], $where)->with(['campus', 'personnel', 'personnel'])->field($field)->order($order); $search_model = $this->model->withSearch(["campus_id", "class_name", "head_coach", "class_type", "assistant_coach", "created_at", "status"], $where)->with(['campus', 'personnel', 'personnel'])->field($field)->order($order);
@ -56,7 +56,7 @@ class ClassroomService extends BaseAdminService
*/ */
public function getInfo(int $id) public function getInfo(int $id)
{ {
$field = 'id,campus_id,campus_name,class_name,head_coach,age_group,class_type,assistant_coach,created_at,updated_at,deleted_at,status,sort_order,remarks'; $field = 'id,campus_id,campus_name,class_name,educational_id,head_coach,age_group,class_type,assistant_coach,created_at,updated_at,deleted_at,status,sort_order,remarks';
$info = $this->model->field($field)->where([['id', "=", $id]])->with(['campus', 'personnel', 'personnel'])->findOrEmpty()->toArray(); $info = $this->model->field($field)->where([['id', "=", $id]])->with(['campus', 'personnel', 'personnel'])->findOrEmpty()->toArray();
$info['status'] = strval($info['status']); $info['status'] = strval($info['status']);

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

@ -420,7 +420,7 @@ class CustomerResourcesService extends BaseAdminService
->field("a.*,b.name,b.phone") ->field("a.*,b.name,b.phone")
->where([ ->where([
['a.campus_id', '=', $campus_id], ['a.campus_id', '=', $campus_id],
['a.role_id', '=', 5] // ['a.role_id', '=', 5]
])->select()->toArray(); ])->select()->toArray();
} }

15
niucloud/app/service/admin/order_table/OrderTableService.php

@ -87,12 +87,15 @@ class OrderTableService extends BaseAdminService
public function add(array $data) public function add(array $data)
{ {
$personnel = new Personnel(); $personnel = new Personnel();
// $data['staff_id'] = $personnel->where(['sys_user_id' => $this->uid])->value("id"); $data['staff_id'] = $personnel->where(['sys_user_id' => $this->uid])->value("id");
// if(!$data['staff_id']){ if(!$data['staff_id']){
// return fail("操作失败"); return fail("操作失败");
// } }
$cr = new CustomerResources();
$data['campus_id'] = $cr->where(['id' => $data['resource_id']])->value("campus");
$data['staff_id'] = 1; // $data['staff_id'] = 1;
$res = $this->model->create($data); $res = $this->model->create($data);
return success("操作成功"); return success("操作成功");
@ -107,6 +110,8 @@ class OrderTableService extends BaseAdminService
*/ */
public function edit(int $id, array $data) public function edit(int $id, array $data)
{ {
$cr = new CustomerResources();
$data['campus_id'] = $cr->where(['id' => $data['resource_id']])->value("campus");
$this->model->where([['id', '=', $id]])->update($data); $this->model->where([['id', '=', $id]])->update($data);
return true; return true;

26
niucloud/app/service/admin/pay/PayService.php

@ -14,6 +14,7 @@ namespace app\service\admin\pay;
use app\dict\common\ChannelDict; use app\dict\common\ChannelDict;
use app\dict\pay\PayDict; use app\dict\pay\PayDict;
use app\dict\pay\PaySceneDict; use app\dict\pay\PaySceneDict;
use app\model\campus_pay\CampusPay;
use app\model\customer_resources\CustomerResources; use app\model\customer_resources\CustomerResources;
use app\model\member\Member; use app\model\member\Member;
use app\model\order_table\OrderTable; use app\model\order_table\OrderTable;
@ -245,8 +246,29 @@ class PayService extends BaseAdminService
$path = qrcode($url['code_url'], '', [], 'upload/qrcode/pay/'); $path = qrcode($url['code_url'], '', [], 'upload/qrcode/pay/');
$order->where(['id' => $data['order_id']])->update(['payment_id' => $out_trade_no, 'ipv3' => $config['mch_secret_key']]); $order->where(['id' => $data['order_id']])->update(['payment_id' => $out_trade_no,'ipv3' => $config['mch_secret_key']]);
return ['qrcode_url' => getCurrentDomain() . $path, 'out_trade_no' => $out_trade_no, 'code_url' => $url['code_url']];
$payModel = new Pay();
$campus_pay = new CampusPay();
$campus_pay_info = $campus_pay->where(['campus_id' => $order_info['campus_id']])->findOrEmpty()->toArray();
$payModel->insert([
'main_id' => $resource_info['member_id'],
'from_main_id' => $resource_info['member_id'],
'out_trade_no' => $out_trade_no,
'trade_type' => '',
'trade_id' => $data['order_id'],
'trade_no' => $out_trade_no,
'body' => '扫码支付',
'money' => $order_info['order_amount'],
'status' => 0,
'create_time' => time(),
'type' => $order_info['payment_type'],
'mch_id' => $campus_pay_info['mchid'],
'main_type' => $order_info['payment_type'],
'channel' => '微信扫码支付'
]);
return ['qrcode_url' => getCurrentDomain().$path,'out_trade_no'=>$out_trade_no];
} }
public function check_payment_status($data) public function check_payment_status($data)

5
niucloud/app/service/api/pay/PayService.php

@ -180,6 +180,11 @@ class PayService extends BaseApiService
$order->where(['payment_id' => $info['out_trade_no']])->update(['order_status' => 'paid','payment_time' => date("Y-m-d H:i:s")]); $order->where(['payment_id' => $info['out_trade_no']])->update(['order_status' => 'paid','payment_time' => date("Y-m-d H:i:s")]);
$payModel = new Pay();
$payModel->where(['trade_id' => $order_id])->update([
'status' => 2,
'pay_time' => time()
]);
event('Student', ['event_type' => 'add','data' => $order_info]); event('Student', ['event_type' => 'add','data' => $order_info]);
} }

Loading…
Cancel
Save