feat: 优化后台录取进度查询逻辑
This commit is contained in:
@@ -574,7 +574,7 @@ function itstudio_join_parse_result_rows_to_records($rows) {
|
||||
'qq' => itstudio_join_normalize_lookup_value('qq', $qq),
|
||||
'email' => itstudio_join_normalize_lookup_value('email', $email),
|
||||
'student_id' => itstudio_join_normalize_lookup_value('student_id', $student_id),
|
||||
'phone' => preg_replace('/\D+/', '', $phone),
|
||||
'phone' => itstudio_join_normalize_lookup_value('phone', $phone),
|
||||
'passed' => ($passed_raw === '1'),
|
||||
);
|
||||
|
||||
@@ -927,7 +927,7 @@ function itstudio_join_normalize_lookup_value($field, $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($field === 'qq') {
|
||||
if ($field === 'qq' || $field === 'phone') {
|
||||
return preg_replace('/\D+/', '', $value);
|
||||
}
|
||||
|
||||
@@ -972,6 +972,12 @@ function itstudio_join_detect_progress_query_identity($raw_identity) {
|
||||
$digits = $compacted;
|
||||
$len = strlen($digits);
|
||||
|
||||
if (preg_match('/^1[3-9]\d{9}$/', $digits)) {
|
||||
$detected['field'] = 'phone';
|
||||
$detected['value'] = itstudio_join_normalize_lookup_value('phone', $digits);
|
||||
return $detected;
|
||||
}
|
||||
|
||||
if ($len >= 10 && $len <= 12) {
|
||||
$detected['field'] = 'student_id';
|
||||
$detected['value'] = itstudio_join_normalize_lookup_value('student_id', $digits);
|
||||
@@ -1069,7 +1075,7 @@ function itstudio_join_record_matches_query($record, $query) {
|
||||
$query = is_array($query) ? $query : array();
|
||||
$has_any_query = false;
|
||||
|
||||
foreach (array('name', 'qq', 'email', 'student_id') as $field) {
|
||||
foreach (array('name', 'qq', 'email', 'student_id', 'phone') as $field) {
|
||||
$q = trim((string) ($query[$field] ?? ''));
|
||||
if ($q === '') {
|
||||
continue;
|
||||
@@ -1089,19 +1095,19 @@ function itstudio_join_find_record_in_stage_results($settings, $stage_key, $quer
|
||||
if (itstudio_join_is_file_result_mode($settings)) {
|
||||
$attachment_id = itstudio_join_get_result_file_attachment_id($settings, $stage_key);
|
||||
if ($attachment_id <= 0) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
$rows = itstudio_join_read_result_rows_from_attachment($attachment_id);
|
||||
$records = itstudio_join_parse_result_rows_to_records($rows);
|
||||
if (empty($records)) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
foreach ($records as $record) {
|
||||
if (itstudio_join_record_matches_query($record, $query) && !empty($record['passed'])) {
|
||||
return true;
|
||||
if (itstudio_join_record_matches_query($record, $query)) {
|
||||
return !empty($record['passed']);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (itstudio_join_is_formidable_result_mode($settings)) {
|
||||
@@ -1115,7 +1121,7 @@ function itstudio_join_find_record_in_stage_results($settings, $stage_key, $quer
|
||||
}
|
||||
$entry_id = (int) $entry_cache[$cache_key];
|
||||
if ($entry_id <= 0) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return itstudio_join_formidable_entry_matches_stage($settings, $entry_id, $stage_key);
|
||||
}
|
||||
@@ -1123,17 +1129,17 @@ function itstudio_join_find_record_in_stage_results($settings, $stage_key, $quer
|
||||
$field_map = itstudio_join_get_result_field_map();
|
||||
$field_key = isset($field_map[$stage_key]) ? $field_map[$stage_key] : '';
|
||||
if ($field_key === '') {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
$raw = (string) ($settings[$field_key] ?? '');
|
||||
if (trim($raw) === '') {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
$records = itstudio_join_parse_result_records($raw);
|
||||
if (empty($records)) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
@@ -1142,7 +1148,15 @@ function itstudio_join_find_record_in_stage_results($settings, $stage_key, $quer
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
function itstudio_join_progress_record_not_found_response($response) {
|
||||
$response = is_array($response) ? $response : array();
|
||||
$response['message_cn'] = '未查询到该报名者,请检查输入信息是否正确。';
|
||||
$response['message_en'] = 'No matching applicant was found. Please check the information and try again.';
|
||||
$response['tone'] = 'warning';
|
||||
return $response;
|
||||
}
|
||||
|
||||
function itstudio_join_get_stage_status_by_key($runtime, $stage_key) {
|
||||
@@ -1188,6 +1202,7 @@ function itstudio_join_resolve_progress_lookup($runtime = array(), $request_sour
|
||||
'qq' => '',
|
||||
'email' => '',
|
||||
'student_id' => '',
|
||||
'phone' => '',
|
||||
);
|
||||
if ($detected_identity['field'] !== '') {
|
||||
$query[$detected_identity['field']] = (string) $detected_identity['value'];
|
||||
@@ -1216,15 +1231,15 @@ function itstudio_join_resolve_progress_lookup($runtime = array(), $request_sour
|
||||
}
|
||||
|
||||
if (!$has_input_value) {
|
||||
$response['message_cn'] = '请输入姓名(中文)/ QQ / 邮箱 / 学号。';
|
||||
$response['message_en'] = 'Please enter Name (Chinese) / QQ / Email / Student ID.';
|
||||
$response['message_cn'] = '请输入姓名(中文)/ QQ / 邮箱 / 学号 / 手机号。';
|
||||
$response['message_en'] = 'Please enter Name (Chinese) / QQ / Email / Student ID / Phone.';
|
||||
$response['tone'] = 'warning';
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!$has_query_value) {
|
||||
$response['message_cn'] = '无法识别输入内容,请输入姓名(中文)/ QQ / 邮箱 / 学号。';
|
||||
$response['message_en'] = 'Input cannot be recognized. Please enter Name (Chinese) / QQ / Email / Student ID.';
|
||||
$response['message_cn'] = '无法识别输入内容,请输入姓名(中文)/ QQ / 邮箱 / 学号 / 手机号。';
|
||||
$response['message_en'] = 'Input cannot be recognized. Please enter Name (Chinese) / QQ / Email / Student ID / Phone.';
|
||||
$response['tone'] = 'warning';
|
||||
return $response;
|
||||
}
|
||||
@@ -1262,6 +1277,9 @@ function itstudio_join_resolve_progress_lookup($runtime = array(), $request_sour
|
||||
}
|
||||
|
||||
$passed_first = itstudio_join_find_record_in_stage_results($settings, 'first_interview', $query);
|
||||
if ($passed_first === null) {
|
||||
return itstudio_join_progress_record_not_found_response($response);
|
||||
}
|
||||
if (!$passed_first) {
|
||||
$response['message_cn'] = '未通过第一次面试,期待来年再次报名。';
|
||||
$response['message_en'] = 'You did not pass Interview I. Welcome to apply again next year.';
|
||||
@@ -1286,6 +1304,9 @@ function itstudio_join_resolve_progress_lookup($runtime = array(), $request_sour
|
||||
}
|
||||
|
||||
$passed_assessment = itstudio_join_find_record_in_stage_results($settings, 'assessment', $query);
|
||||
if ($passed_assessment === null) {
|
||||
return itstudio_join_progress_record_not_found_response($response);
|
||||
}
|
||||
if (!$passed_assessment) {
|
||||
$response['message_cn'] = '未通过国庆能力摸底,期待来年再次报名。';
|
||||
$response['message_en'] = 'You did not pass the assessment stage. Welcome to apply again next year.';
|
||||
@@ -1310,6 +1331,9 @@ function itstudio_join_resolve_progress_lookup($runtime = array(), $request_sour
|
||||
}
|
||||
|
||||
$passed_second = itstudio_join_find_record_in_stage_results($settings, 'second_interview', $query);
|
||||
if ($passed_second === null) {
|
||||
return itstudio_join_progress_record_not_found_response($response);
|
||||
}
|
||||
if (!$passed_second) {
|
||||
$response['message_cn'] = '未通过第二次面试,期待来年再次报名。';
|
||||
$response['message_en'] = 'You did not pass Interview II. Welcome to apply again next year.';
|
||||
@@ -1320,6 +1344,9 @@ function itstudio_join_resolve_progress_lookup($runtime = array(), $request_sour
|
||||
if ($status_notice === 'pending' || $status_notice === 'upcoming' || $status_notice === 'active') {
|
||||
if ($status_notice === 'active' && $uploaded_notice) {
|
||||
$admitted = itstudio_join_find_record_in_stage_results($settings, 'public_notice', $query);
|
||||
if ($admitted === null) {
|
||||
return itstudio_join_progress_record_not_found_response($response);
|
||||
}
|
||||
if ($admitted) {
|
||||
$response['message_cn'] = '恭喜,您已被录取。';
|
||||
$response['message_en'] = 'Congratulations! You have been admitted.';
|
||||
@@ -1342,6 +1369,9 @@ function itstudio_join_resolve_progress_lookup($runtime = array(), $request_sour
|
||||
|
||||
if (($status_notice === 'active' || $status_notice === 'completed') && $uploaded_notice) {
|
||||
$admitted = itstudio_join_find_record_in_stage_results($settings, 'public_notice', $query);
|
||||
if ($admitted === null) {
|
||||
return itstudio_join_progress_record_not_found_response($response);
|
||||
}
|
||||
if ($admitted) {
|
||||
$response['message_cn'] = '恭喜,您已被录取。';
|
||||
$response['message_en'] = 'Congratulations! You have been admitted.';
|
||||
@@ -1952,6 +1982,15 @@ function itstudio_join_register_settings_page() {
|
||||
}
|
||||
add_action('admin_menu', 'itstudio_join_register_settings_page');
|
||||
|
||||
function itstudio_join_enqueue_settings_page_media($hook_suffix) {
|
||||
if ($hook_suffix !== 'settings_page_itstudio-join-settings') {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_media();
|
||||
}
|
||||
add_action('admin_enqueue_scripts', 'itstudio_join_enqueue_settings_page_media');
|
||||
|
||||
/**
|
||||
* 统一跳回招新设置页并带上提示参数。
|
||||
*/
|
||||
@@ -1970,11 +2009,50 @@ function itstudio_join_settings_error_message($code) {
|
||||
'delete_last' => '至少要保留一个学期。',
|
||||
'delete_failed' => '删除失败,学期不存在。',
|
||||
'save_failed' => '保存失败,学期不存在。',
|
||||
'result_upload_failed' => '结果文件上传失败,请确认文件为 CSV 或 XLSX 后重试。',
|
||||
'need_year' => '请填写学年或自定义名称。',
|
||||
);
|
||||
return isset($map[$code]) ? $map[$code] : '操作失败。';
|
||||
}
|
||||
|
||||
function itstudio_join_handle_result_file_uploads($settings) {
|
||||
$settings = is_array($settings) ? $settings : array();
|
||||
|
||||
foreach (itstudio_join_get_result_file_field_map() as $field_key) {
|
||||
$upload_key = 'itstudio_join_upload_' . $field_key;
|
||||
if (!isset($_FILES[$upload_key]) || !is_array($_FILES[$upload_key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$upload_error = isset($_FILES[$upload_key]['error']) ? (int) $_FILES[$upload_key]['error'] : UPLOAD_ERR_NO_FILE;
|
||||
if ($upload_error === UPLOAD_ERR_NO_FILE) {
|
||||
continue;
|
||||
}
|
||||
if ($upload_error !== UPLOAD_ERR_OK) {
|
||||
return new WP_Error('result_upload_failed');
|
||||
}
|
||||
|
||||
$filename = isset($_FILES[$upload_key]['name']) ? sanitize_file_name(wp_unslash($_FILES[$upload_key]['name'])) : '';
|
||||
$extension = strtolower((string) pathinfo($filename, PATHINFO_EXTENSION));
|
||||
if (!in_array($extension, array('csv', 'xlsx'), true)) {
|
||||
return new WP_Error('result_upload_failed');
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
|
||||
$attachment_id = media_handle_upload($upload_key, 0);
|
||||
if (is_wp_error($attachment_id)) {
|
||||
return new WP_Error('result_upload_failed', $attachment_id->get_error_message());
|
||||
}
|
||||
|
||||
$settings[$field_key] = absint($attachment_id);
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存某学期的配置(含学期元信息)。
|
||||
*/
|
||||
@@ -1988,6 +2066,11 @@ function itstudio_join_handle_save_term_settings() {
|
||||
$raw = (isset($_POST['itstudio_join_settings']) && is_array($_POST['itstudio_join_settings'])) ? wp_unslash($_POST['itstudio_join_settings']) : array();
|
||||
$meta = (isset($_POST['itstudio_join_term_meta']) && is_array($_POST['itstudio_join_term_meta'])) ? wp_unslash($_POST['itstudio_join_term_meta']) : array();
|
||||
|
||||
$raw = itstudio_join_handle_result_file_uploads($raw);
|
||||
if (is_wp_error($raw)) {
|
||||
itstudio_join_settings_redirect(array('term' => $term_id, 'error' => $raw->get_error_code()));
|
||||
}
|
||||
|
||||
if (!empty($meta)) {
|
||||
itstudio_join_update_term_meta(
|
||||
$term_id,
|
||||
@@ -2133,15 +2216,58 @@ function itstudio_join_render_result_file_row($field_key, $label, $settings, $de
|
||||
$attachment_id = isset($settings[$field_key]) ? absint($settings[$field_key]) : 0;
|
||||
$file_url = $attachment_id > 0 ? wp_get_attachment_url($attachment_id) : '';
|
||||
$filename = $attachment_id > 0 ? basename((string) get_attached_file($attachment_id)) : '';
|
||||
static $result_files = null;
|
||||
if ($result_files === null) {
|
||||
$result_files = get_posts(array(
|
||||
'post_type' => 'attachment',
|
||||
'post_status' => 'inherit',
|
||||
'post_mime_type' => array(
|
||||
'text/csv',
|
||||
'application/csv',
|
||||
'application/vnd.ms-excel',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
),
|
||||
'posts_per_page' => 100,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
));
|
||||
}
|
||||
if ($attachment_id > 0 && !in_array($attachment_id, wp_list_pluck($result_files, 'ID'), true)) {
|
||||
$current_file = get_post($attachment_id);
|
||||
if ($current_file instanceof WP_Post && $current_file->post_type === 'attachment') {
|
||||
$result_files[] = $current_file;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><label><?php echo esc_html($label); ?></label></th>
|
||||
<td>
|
||||
<input type="hidden" class="itstudio-join-result-file-id" name="itstudio_join_settings[<?php echo esc_attr($field_key); ?>]" value="<?php echo esc_attr($attachment_id); ?>">
|
||||
<div class="itstudio-join-result-file-preview" style="margin-bottom:10px;<?php echo $file_url !== '' ? '' : 'display:none;'; ?>">
|
||||
<a class="itstudio-join-result-file-link" href="<?php echo esc_url($file_url); ?>" target="_blank" rel="noopener"><?php echo esc_html($filename !== '' ? $filename : $file_url); ?></a>
|
||||
</div>
|
||||
<button type="button" class="button itstudio-join-result-file-upload"><?php esc_html_e('上传 / 选择结果文件', 'itstudio'); ?></button>
|
||||
<select class="itstudio-join-result-file-id" name="itstudio_join_settings[<?php echo esc_attr($field_key); ?>]">
|
||||
<option value="0">不选择已有文件</option>
|
||||
<?php foreach ($result_files as $result_file) : ?>
|
||||
<?php
|
||||
$result_file_id = absint($result_file->ID);
|
||||
$result_file_url = wp_get_attachment_url($result_file_id);
|
||||
$result_file_name = basename((string) get_attached_file($result_file_id));
|
||||
?>
|
||||
<option
|
||||
value="<?php echo esc_attr($result_file_id); ?>"
|
||||
data-url="<?php echo esc_url($result_file_url); ?>"
|
||||
data-filename="<?php echo esc_attr($result_file_name); ?>"
|
||||
<?php selected($attachment_id, $result_file_id); ?>
|
||||
><?php echo esc_html($result_file_name !== '' ? $result_file_name : $result_file->post_title); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input
|
||||
type="file"
|
||||
class="itstudio-join-result-file-upload"
|
||||
name="<?php echo esc_attr('itstudio_join_upload_' . $field_key); ?>"
|
||||
accept=".csv,.xlsx,text/csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
style="display:block;margin-top:8px;"
|
||||
>
|
||||
<button type="button" class="button-link-delete itstudio-join-result-file-clear" style="margin-left:8px;<?php echo $file_url !== '' ? '' : 'display:none;'; ?>"><?php esc_html_e('移除', 'itstudio'); ?></button>
|
||||
<?php if ($description !== '') : ?>
|
||||
<p class="description"><?php echo esc_html($description); ?></p>
|
||||
@@ -2158,8 +2284,6 @@ function itstudio_join_render_settings_page() {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_media();
|
||||
|
||||
$terms = itstudio_join_get_terms();
|
||||
$active_id = itstudio_join_get_active_term_id();
|
||||
$editing_term_id = isset($_GET['term']) ? sanitize_text_field(wp_unslash($_GET['term'])) : '';
|
||||
@@ -2259,7 +2383,7 @@ function itstudio_join_render_settings_page() {
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form method="post" action="<?php echo esc_url($admin_post_url); ?>">
|
||||
<form method="post" action="<?php echo esc_url($admin_post_url); ?>" enctype="multipart/form-data">
|
||||
<input type="hidden" name="action" value="itstudio_join_save_term_settings">
|
||||
<input type="hidden" name="itstudio_join_term_id" value="<?php echo esc_attr($editing_term_id); ?>">
|
||||
<?php wp_nonce_field('itstudio_join_save_term_settings'); ?>
|
||||
@@ -2527,56 +2651,27 @@ function itstudio_join_render_settings_page() {
|
||||
});
|
||||
});
|
||||
|
||||
const resultFileButtons = document.querySelectorAll('.itstudio-join-result-file-upload');
|
||||
resultFileButtons.forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
if (!window.wp || !wp.media) {
|
||||
return;
|
||||
document.querySelectorAll('.itstudio-join-result-file-id').forEach((select) => {
|
||||
select.addEventListener('change', () => {
|
||||
const row = select.closest('td');
|
||||
const option = select.options[select.selectedIndex];
|
||||
const preview = row ? row.querySelector('.itstudio-join-result-file-preview') : null;
|
||||
const link = row ? row.querySelector('.itstudio-join-result-file-link') : null;
|
||||
const clearBtn = row ? row.querySelector('.itstudio-join-result-file-clear') : null;
|
||||
const upload = row ? row.querySelector('.itstudio-join-result-file-upload') : null;
|
||||
const fileUrl = option ? option.dataset.url || '' : '';
|
||||
const filename = option ? option.dataset.filename || '' : '';
|
||||
if (upload) {
|
||||
upload.value = '';
|
||||
}
|
||||
|
||||
const row = button.closest('td');
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
const input = row.querySelector('.itstudio-join-result-file-id');
|
||||
const preview = row.querySelector('.itstudio-join-result-file-preview');
|
||||
const link = row.querySelector('.itstudio-join-result-file-link');
|
||||
const clearBtn = row.querySelector('.itstudio-join-result-file-clear');
|
||||
if (!input || !preview || !link) {
|
||||
return;
|
||||
}
|
||||
|
||||
const frame = wp.media({
|
||||
title: '选择结果文件',
|
||||
button: { text: '使用此文件' },
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
frame.on('select', () => {
|
||||
const selection = frame.state().get('selection').first();
|
||||
if (!selection) {
|
||||
return;
|
||||
}
|
||||
const data = selection.toJSON();
|
||||
const fileUrl = data.url || '';
|
||||
const filename = data.filename || (fileUrl ? fileUrl.split('/').pop() : '');
|
||||
const ext = filename.includes('.') ? filename.split('.').pop().toLowerCase() : '';
|
||||
if (!['csv', 'xlsx'].includes(ext)) {
|
||||
window.alert('请上传 CSV 或 XLSX 文件。');
|
||||
return;
|
||||
}
|
||||
|
||||
input.value = data.id || '';
|
||||
if (preview && link) {
|
||||
link.href = fileUrl || '#';
|
||||
link.textContent = filename || fileUrl || '';
|
||||
link.textContent = filename || fileUrl;
|
||||
preview.style.display = fileUrl ? 'block' : 'none';
|
||||
if (clearBtn) {
|
||||
clearBtn.style.display = fileUrl ? 'inline' : 'none';
|
||||
}
|
||||
});
|
||||
|
||||
frame.open();
|
||||
}
|
||||
if (clearBtn) {
|
||||
clearBtn.style.display = fileUrl ? 'inline' : 'none';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2587,10 +2682,14 @@ function itstudio_join_render_settings_page() {
|
||||
return;
|
||||
}
|
||||
const input = row.querySelector('.itstudio-join-result-file-id');
|
||||
const upload = row.querySelector('.itstudio-join-result-file-upload');
|
||||
const preview = row.querySelector('.itstudio-join-result-file-preview');
|
||||
const link = row.querySelector('.itstudio-join-result-file-link');
|
||||
if (input) {
|
||||
input.value = '';
|
||||
input.value = '0';
|
||||
}
|
||||
if (upload) {
|
||||
upload.value = '';
|
||||
}
|
||||
if (link) {
|
||||
link.href = '#';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: ITStudio 招新系统
|
||||
* Plugin URI: https://git.itouc.cn/ITStudio_OUC/ITStudioMainSite
|
||||
|
||||
Reference in New Issue
Block a user