Browse Source

修改 bug

master
王泽彦 7 months ago
parent
commit
94629057b7
  1. 48
      admin/src/app/views/campus/campus.vue
  2. 38
      niucloud/app/api/controller/apiController/Contract.php
  3. 2
      niucloud/app/api/route/route.php
  4. 297
      niucloud/app/service/api/apiService/ContractSignFormService.php
  5. 12
      niucloud/app/service/api/apiService/OrderTableService.php
  6. 8
      uniapp/api/apiRoute.js
  7. 21
      uniapp/pages-market/clue/clue_info.vue
  8. 25
      uniapp/pages-student/contracts/sign.vue

48
admin/src/app/views/campus/campus.vue

@ -139,7 +139,7 @@
<el-dialog <el-dialog
v-model="sealDialog.visible" v-model="sealDialog.visible"
title="上传签章" title="上传签章"
width="500px" width="600px"
:close-on-click-modal="false" :close-on-click-modal="false"
> >
<el-form :model="sealDialog.form" label-width="80px"> <el-form :model="sealDialog.form" label-width="80px">
@ -232,7 +232,7 @@ const sealDialog = reactive({
}) })
// //
const uploadAction = `${import.meta.env.VITE_APP_BASE_URL}/adminapi/upload/file` const uploadAction = `${import.meta.env.VITE_APP_BASE_URL}sys/image`
const uploadHeaders = { const uploadHeaders = {
token: getToken() token: getToken()
} }
@ -398,4 +398,48 @@ const saveSeal = async () => {
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
/* 修复上传组件在弹窗中的样式 */
.upload-demo {
width: 100%;
:deep(.el-upload-list--picture-card) {
--el-upload-list-picture-card-size: 100px;
display: flex;
flex-wrap: wrap;
margin: 0 0 10px 0;
}
:deep(.el-upload--picture-card) {
--el-upload-picture-card-size: 100px;
width: var(--el-upload-picture-card-size);
height: var(--el-upload-picture-card-size);
line-height: calc(var(--el-upload-picture-card-size) - 2px);
margin-bottom: 10px;
}
:deep(.el-upload-list__item) {
width: var(--el-upload-list-picture-card-size);
height: var(--el-upload-list-picture-card-size);
margin: 0 8px 10px 0;
}
/* 确保上传区域不超出弹窗 */
:deep(.el-upload-dragger) {
width: 100%;
height: 100px;
}
/* 修复提示文字被盖住的问题 */
:deep(.el-upload__tip) {
margin-top: 25%;
line-height: 1.4;
color: var(--el-text-color-regular);
font-size: 12px;
position: relative;
z-index: 1;
clear: both;
display: block;
}
}
</style> </style>

38
niucloud/app/api/controller/apiController/Contract.php

@ -254,6 +254,44 @@ class Contract extends BaseApiService
} }
} }
/**
* 根据签署记录ID获取学生合同签署表单配置(新方法)
* 支持按签署关系区分不同订单的签署字段
* @param Request $request
* @return mixed
*/
public function getStudentContractSignFormBySignId(Request $request)
{
$contract_sign_id = $request->param('contract_sign_id', 0);
$student_id = $request->param('student_id', 0);
if (empty($contract_sign_id)) {
return fail('合同签署记录ID不能为空');
}
if (empty($student_id)) {
return fail('学生ID不能为空');
}
$params = [
'contract_sign_id' => $contract_sign_id,
'student_id' => $student_id
];
try {
$service = new ContractSignFormService();
$res = $service->getStudentContractSignFormBySignId($params);
if (!$res['code']) {
return fail($res['msg']);
}
return success($res['data']);
} catch (\Exception $e) {
return fail('获取签署表单失败:' . $e->getMessage());
}
}
/** /**
* 提交学生合同签署 * 提交学生合同签署
* @param Request $request * @param Request $request

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

@ -464,6 +464,8 @@ Route::group(function () {
// 学生合同签署相关接口 // 学生合同签署相关接口
Route::get('contract/getStudentContractSignForm', 'apiController.Contract/getStudentContractSignForm'); Route::get('contract/getStudentContractSignForm', 'apiController.Contract/getStudentContractSignForm');
Route::post('contract/submitStudentContractSign', 'apiController.Contract/submitStudentContractSign'); Route::post('contract/submitStudentContractSign', 'apiController.Contract/submitStudentContractSign');
// 新增:根据签署记录ID获取签署表单(支持按签署关系区分字段)
Route::get('contract/getStudentContractSignFormBySignId', 'apiController.Contract/getStudentContractSignFormBySignId');
// 前端期望的路由路径(映射到相同的控制器方法) // 前端期望的路由路径(映射到相同的控制器方法)
Route::get('student/contract/sign-form', 'apiController.Contract/getStudentContractSignForm'); Route::get('student/contract/sign-form', 'apiController.Contract/getStudentContractSignForm');

297
niucloud/app/service/api/apiService/ContractSignFormService.php

@ -28,6 +28,103 @@ class ContractSignFormService extends BaseApiService
parent::__construct(); parent::__construct();
} }
/**
* 根据合同签署记录ID获取签署表单配置
* 优先使用contract_sign_id获取该签署关系专属的字段配置
*
* @param array $params 请求参数
* - contract_sign_id: 合同签署记录ID (优先)
* - contract_id: 合同模板ID (兼容旧版本)
* - student_id: 学员ID (必填)
* @return array 返回格式化的表单配置数据
*/
public function getStudentContractSignFormBySignId(array $params)
{
try {
// 验证必要参数
if (empty($params['contract_sign_id']) || empty($params['student_id'])) {
throw new \Exception('缺少必要参数:contract_sign_id 和 student_id');
}
$contract_sign_id = (int)$params['contract_sign_id'];
$student_id = (int)$params['student_id'];
Log::info('根据签署记录ID获取合同签署表单', [
'contract_sign_id' => $contract_sign_id,
'student_id' => $student_id
]);
// 1. 从签署记录获取合同ID
$sign_record = Db::table('school_contract_sign')
->where('id', $contract_sign_id)
->where('student_id', $student_id)
->find();
if (!$sign_record) {
throw new \Exception('合同签署记录不存在');
}
$contract_id = $sign_record['contract_id'];
// 2. 获取合同模板基本信息
$contract = $this->getContractInfo($contract_id);
if (!$contract) {
throw new \Exception('合同模板不存在或已删除');
}
// 3. 获取学员基本信息
$student = $this->getStudentInfo($student_id);
if (!$student) {
throw new \Exception('学员信息不存在');
}
// 4. 从document_data_source_config表获取该签署关系专属的字段配置
$form_fields = $this->getSignSpecificFormFields($contract_sign_id, $student);
// 5. 组装返回数据
$result = [
'contract_id' => $contract_id,
'contract_sign_id' => $contract_sign_id,
'contract_name' => $contract['contract_name'],
'contract_type' => $contract['contract_type'],
'contract_content' => $contract['contract_content'] ?? '',
'form_fields' => $form_fields,
'student_info' => [
'id' => $student['id'],
'name' => $student['name'],
'phone' => $student['contact_phone'] ?? '',
'user_id' => $student['user_id']
]
];
Log::info('根据签署记录ID获取表单成功', [
'contract_sign_id' => $contract_sign_id,
'student_id' => $student_id,
'form_fields_count' => count($form_fields)
]);
return [
'code' => 1,
'msg' => '获取成功',
'data' => $result
];
} catch (\Exception $e) {
Log::error('根据签署记录ID获取表单失败', [
'contract_sign_id' => $params['contract_sign_id'] ?? 0,
'student_id' => $params['student_id'] ?? 0,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return [
'code' => 0,
'msg' => $e->getMessage(),
'data' => []
];
}
}
/** /**
* 获取学员合同签署表单配置 * 获取学员合同签署表单配置
* 该方法为移动端提供合同签署表单的完整配置信息 * 该方法为移动端提供合同签署表单的完整配置信息
@ -598,4 +695,204 @@ class ContractSignFormService extends BaseApiService
return false; return false;
} }
} }
/**
* 获取签署关系专属的表单字段
* @param int $contract_sign_id 合同签署记录ID
* @param array $student 学员信息
* @return array
*/
private function getSignSpecificFormFields($contract_sign_id, $student)
{
try {
// 从document_data_source_config表获取该签署关系专属的字段配置
$configs = Db::table('school_document_data_source_config')
->where('contract_sign_id', $contract_sign_id)
->select()
->toArray();
if (empty($configs)) {
Log::warning('该签署记录无字段配置', ['contract_sign_id' => $contract_sign_id]);
return [];
}
$form_fields = [];
foreach ($configs as $config) {
// 基础字段信息
$field = [
'name' => $config['placeholder'] ?? '',
'placeholder' => $config['placeholder'] ?? '',
'data_type' => $config['data_type'] ?? 'user_input',
'field_type' => $config['field_type'] ?? 'text',
'is_required' => (int)($config['is_required'] ?? 0),
'default_value' => '',
'validation_rule' => $config['validation_rule'] ?? '',
'sign_party' => $config['sign_party'] ?? '',
];
// 根据数据类型处理默认值
switch ($config['data_type'] ?? 'user_input') {
case 'database':
// 数据库类型:从相关表获取数据
$field['default_value'] = $this->getDatabaseFieldValueFromConfig($config, $student);
break;
case 'system':
// 系统函数类型:调用系统函数获取值
$field['default_value'] = $this->getSystemFunctionValueFromConfig($config);
break;
case 'user_input':
// 用户输入类型:使用配置的默认值
$field['default_value'] = $config['default_value'] ?? '';
break;
case 'signature':
// 电子签名类型:无默认值,需要用户手写签名
$field['signature_type'] = 'handwrite';
$field['default_value'] = '';
break;
case 'sign_img':
// 签名图片类型:无默认值,需要用户上传或选择
$field['sign_image_source'] = 'upload';
$field['default_value'] = '';
break;
default:
$field['default_value'] = $config['default_value'] ?? '';
break;
}
$form_fields[] = $field;
}
Log::info('获取签署关系专属字段完成', [
'contract_sign_id' => $contract_sign_id,
'fields_count' => count($form_fields)
]);
return $form_fields;
} catch (\Exception $e) {
Log::error('获取签署关系专属字段失败', [
'contract_sign_id' => $contract_sign_id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return [];
}
}
/**
* 从配置中获取数据库字段值
* @param array $config 字段配置
* @param array $student 学员信息
* @return string
*/
private function getDatabaseFieldValueFromConfig($config, $student)
{
try {
$table_name = $config['table_name'] ?? '';
$field_name = $config['field_name'] ?? '';
if (empty($table_name) || empty($field_name)) {
return '';
}
$value = '';
switch ($table_name) {
case 'school_student':
// 学员表:直接从学员信息获取
$value = $student[$field_name] ?? '';
break;
case 'school_customer_resources':
// 用户表:通过学员的user_id关联查询
if (!empty($student['user_id'])) {
$value = Db::table('school_customer_resources')
->where('id', $student['user_id'])
->value($field_name) ?? '';
}
break;
case 'school_order_table':
// 订单表:查询该学员最新的订单信息
$value = Db::table('school_order_table')
->where('student_id', $student['id'])
->order('created_at', 'desc')
->value($field_name) ?? '';
break;
case 'school_personnel':
// 员工表:这里可能需要根据业务逻辑确定关联的员工
// 暂时返回空值,具体业务逻辑需要根据实际需求调整
$value = '';
break;
default:
Log::warning('不支持的数据库表', [
'table_name' => $table_name,
'field_name' => $field_name
]);
break;
}
// 对特殊字段进行格式化处理
$value = $this->formatFieldValue($field_name, $value);
return (string)$value;
} catch (\Exception $e) {
Log::error('从配置获取数据库字段值失败', [
'config' => $config,
'student_id' => $student['id'],
'error' => $e->getMessage()
]);
return '';
}
}
/**
* 从配置中获取系统函数值
* @param array $config 字段配置
* @return string
*/
private function getSystemFunctionValueFromConfig($config)
{
try {
$system_function = $config['system_function'] ?? '';
if (empty($system_function)) {
return '';
}
// 检查函数是否存在
if (!function_exists($system_function)) {
Log::warning('系统函数不存在', [
'function_name' => $system_function
]);
return '';
}
// 调用系统函数
$value = call_user_func($system_function);
Log::info('系统函数调用成功', [
'function_name' => $system_function,
'result' => $value
]);
return (string)$value;
} catch (\Exception $e) {
Log::error('从配置获取系统函数值失败', [
'config' => $config,
'error' => $e->getMessage()
]);
return '';
}
}
} }

12
niucloud/app/service/api/apiService/OrderTableService.php

@ -411,7 +411,7 @@ class OrderTableService extends BaseApiService
'contract_sign_id' => $result // 合同签署记录ID 'contract_sign_id' => $result // 合同签署记录ID
]); ]);
// 创建签署记录成功后,为甲乙双方生成数据源配置记录 // 创建签署记录成功后,为甲乙双方生成数据源配置记录
$this->createDocumentDataSourceConfig($course['contract_id'], $orderData); $this->createDocumentDataSourceConfig($course['contract_id'], $result, $orderData);
\think\facade\Log::info('合同签署记录创建成功', [ \think\facade\Log::info('合同签署记录创建成功', [
'student_id' => $student_id, 'student_id' => $student_id,
@ -433,11 +433,12 @@ class OrderTableService extends BaseApiService
/** /**
* 为甲乙双方创建文档数据源配置记录 * 为甲乙双方创建文档数据源配置记录
* @param int $contract_id 合同ID * @param int $contract_id 合同模板ID
* @param int $contract_sign_id 合同签署记录ID
* @param array $orderData 订单数据 * @param array $orderData 订单数据
* @return bool * @return bool
*/ */
private function createDocumentDataSourceConfig($contract_id, $orderData) private function createDocumentDataSourceConfig($contract_id, $contract_sign_id, $orderData)
{ {
try { try {
// 获取合同模板的占位符配置 // 获取合同模板的占位符配置
@ -456,10 +457,11 @@ class OrderTableService extends BaseApiService
$insert_data = []; $insert_data = [];
$now = date('Y-m-d H:i:s'); $now = date('Y-m-d H:i:s');
// 为每个占位符配置创建数据源记录 // 为每个占位符配置创建数据源记录,关联到具体的签署记录
foreach ($placeholder_config as $config) { foreach ($placeholder_config as $config) {
$data_source_record = [ $data_source_record = [
'contract_id' => $contract_id, 'contract_id' => $contract_id,
'contract_sign_id' => $contract_sign_id, // 新增:关联到具体的签署记录
'placeholder' => $config['placeholder'] ?? '', 'placeholder' => $config['placeholder'] ?? '',
'data_type' => $config['data_type'] ?? 'user_input', 'data_type' => $config['data_type'] ?? 'user_input',
'system_function' => $config['system_function'] ?? '', 'system_function' => $config['system_function'] ?? '',
@ -483,6 +485,7 @@ class OrderTableService extends BaseApiService
if ($result) { if ($result) {
\think\facade\Log::info('文档数据源配置创建成功', [ \think\facade\Log::info('文档数据源配置创建成功', [
'contract_id' => $contract_id, 'contract_id' => $contract_id,
'contract_sign_id' => $contract_sign_id,
'order_id' => $orderData['id'], 'order_id' => $orderData['id'],
'records_count' => count($insert_data) 'records_count' => count($insert_data)
]); ]);
@ -495,6 +498,7 @@ class OrderTableService extends BaseApiService
} catch (\Exception $e) { } catch (\Exception $e) {
\think\facade\Log::error('创建文档数据源配置异常', [ \think\facade\Log::error('创建文档数据源配置异常', [
'contract_id' => $contract_id, 'contract_id' => $contract_id,
'contract_sign_id' => $contract_sign_id,
'order_data' => $orderData, 'order_data' => $orderData,
'error' => $e->getMessage(), 'error' => $e->getMessage(),
'trace' => $e->getTraceAsString() 'trace' => $e->getTraceAsString()

8
uniapp/api/apiRoute.js

@ -1726,6 +1726,14 @@ export default {
}) })
}, },
// 根据签署记录ID获取合同签署表单配置(新方法-支持按签署关系区分字段)
async getStudentContractSignFormBySignId(data = {}) {
return await http.get('/contract/getStudentContractSignFormBySignId', {
contract_sign_id: data.contract_sign_id,
student_id: data.student_id,
})
},
// 提交合同签署 // 提交合同签署
async signStudentContract(data = {}) { async signStudentContract(data = {}) {
return await http.post('/student/contract/sign', { return await http.post('/student/contract/sign', {

21
uniapp/pages-market/clue/clue_info.vue

@ -1199,6 +1199,9 @@ export default {
course_count: order.total_hours || 0, // 使 course_count: order.total_hours || 0, // 使
status: this.mapOrderStatus(order.order_status), status: this.mapOrderStatus(order.order_status),
create_time: order.created_at, create_time: order.created_at,
//
contract_id: order.contract_id,
contract_sign_id: order.contract_sign_id,
// //
_raw: order _raw: order
})) }))
@ -1575,7 +1578,8 @@ ${orderInfo.paid_at ? '支付时间:' + this.formatOrderTime(orderInfo.paid_at
goToContractSign(order) { goToContractSign(order) {
// //
const studentId = order.student_id || this.currentStudent?.id const studentId = order.student_id || this.currentStudent?.id
const contractId = order._raw?.contract_id || order.contract_id const contractId = order.contract_id || order._raw?.contract_id
const contractSignId = order.contract_sign_id || order._raw?.contract_sign_id
if (!studentId) { if (!studentId) {
uni.showToast({ uni.showToast({
@ -1586,15 +1590,22 @@ ${orderInfo.paid_at ? '支付时间:' + this.formatOrderTime(orderInfo.paid_at
} }
if (!contractId) { if (!contractId) {
// ID // ID
// API
this.getContractByOrder(order, studentId) this.getContractByOrder(order, studentId)
return return
} }
// //
let url = `/pages-student/contracts/sign?contract_id=${contractId}&student_id=${studentId}&contract_name=${encodeURIComponent(order.product_name + '合同')}`
// ID
if (contractSignId) {
url += `&contract_sign_id=${contractSignId}`
}
//
uni.navigateTo({ uni.navigateTo({
url: `/pages-student/contracts/sign?contract_id=${contractId}&student_id=${studentId}&contract_name=${encodeURIComponent(order.product_name + '合同')}` url: url
}) })
}, },

25
uniapp/pages-student/contracts/sign.vue

@ -168,6 +168,7 @@
return { return {
contractId: 0, contractId: 0,
studentId: 0, studentId: 0,
contractSignId: 0, // ID
contractName: '', contractName: '',
contractInfo: null, contractInfo: null,
contractContent: '', contractContent: '',
@ -264,6 +265,8 @@
this.contractId = parseInt(options.contract_id) || 0 this.contractId = parseInt(options.contract_id) || 0
this.studentId = parseInt(options.student_id) || 0 this.studentId = parseInt(options.student_id) || 0
this.contractName = decodeURIComponent(options.contract_name || '') this.contractName = decodeURIComponent(options.contract_name || '')
// ID
this.contractSignId = parseInt(options.contract_sign_id) || 0
if (this.contractId && this.studentId) { if (this.contractId && this.studentId) {
this.loadSignForm() this.loadSignForm()
@ -298,13 +301,29 @@
async loadSignForm() { async loadSignForm() {
this.loading = true this.loading = true
try { try {
console.log('加载签署表单:', { contractId: this.contractId, studentId: this.studentId }) console.log('加载签署表单:', {
contractId: this.contractId,
studentId: this.studentId,
contractSignId: this.contractSignId
})
let response;
// // 使contract_sign_id
const response = await apiRoute.getStudentContractSignForm({ if (this.contractSignId && this.contractSignId > 0) {
console.log('使用签署记录ID获取表单配置')
response = await apiRoute.getStudentContractSignFormBySignId({
contract_sign_id: this.contractSignId,
student_id: this.studentId
})
} else {
console.log('使用合同模板ID获取表单配置(兼容模式)')
// 使contract_id
response = await apiRoute.getStudentContractSignForm({
contract_id: this.contractId, contract_id: this.contractId,
student_id: this.studentId student_id: this.studentId
}) })
}
if (response.code === 1) { if (response.code === 1) {
const data = response.data const data = response.data

Loading…
Cancel
Save