|
|
@@ -279,6 +279,20 @@
|
|
|
<a-modal v-model:visible="visible" title="编辑账号" @cancel="handleCancel" @before-ok="handleBeforeOk" draggable
|
|
|
:ok-loading="ok_loading" esc-to-close closable>
|
|
|
<a-form :model="form">
|
|
|
+ <a-form-item label="自动识别" v-if="!form.id">
|
|
|
+ <a-textarea
|
|
|
+ v-model="autoFillText"
|
|
|
+ placeholder="粘贴包含学号、邮箱、跑区等信息的文本,点击“识别并填入”自动填写"
|
|
|
+ :auto-size="{ minRows: 2, maxRows: 4 }"
|
|
|
+ allow-clear
|
|
|
+ />
|
|
|
+ <template #extra>
|
|
|
+ <a-space>
|
|
|
+ <a-button type="primary" @click="handleAutoFill" size="small">识别并填入</a-button>
|
|
|
+ <span class="auto-fill-tip">示例:2023012345,abc@ctbu.edu.cn,南山校区</span>
|
|
|
+ </a-space>
|
|
|
+ </template>
|
|
|
+ </a-form-item>
|
|
|
<a-form-item field="student_num" label="学号">
|
|
|
<a-input v-model="form.student_num" placeholder="账号所有者学号,填写错误将无法登录" allow-clear />
|
|
|
</a-form-item>
|
|
|
@@ -306,7 +320,7 @@
|
|
|
<a-form-item field="auto_run" label="自动乐跑开关">
|
|
|
<a-switch v-model="form.auto_run" :checked-value="1" :unchecked-value="0" />
|
|
|
</a-form-item>
|
|
|
- <a-form-item field="target_count" label="目标里程(km)" v-if="form.auto_run">
|
|
|
+ <a-form-item field="target_count" label="月度目标里程" v-if="form.auto_run">
|
|
|
<a-input-number v-model="form.target_count" placeholder="0–200,0 表示不限制" mode="button" :min="0" :max="200"
|
|
|
:precision="2" :step="0.5" />
|
|
|
<template #extra>
|
|
|
@@ -494,6 +508,7 @@ const loading = ref(false)
|
|
|
|
|
|
const visible = ref(false)
|
|
|
const ok_loading = ref(false)
|
|
|
+const autoFillText = ref('')
|
|
|
const form = reactive({
|
|
|
id: null,
|
|
|
student_num: '',
|
|
|
@@ -531,6 +546,59 @@ const download = (device) => {
|
|
|
document.body.removeChild(a)
|
|
|
}
|
|
|
|
|
|
+const normalizeText = (value) => (value || '').replace(/[\n\r\t,;、]/g, ' ').trim()
|
|
|
+
|
|
|
+const matchArea = (text) => {
|
|
|
+ const normalized = normalizeText(text)
|
|
|
+ if (!normalized) return null
|
|
|
+
|
|
|
+ const exact = area.find(item => normalized.includes(item))
|
|
|
+ if (exact) return exact
|
|
|
+
|
|
|
+ const areaAliasMap = [
|
|
|
+ { keywords: ['南山'], value: '南山校区' },
|
|
|
+ { keywords: ['学府'], value: '学府大道校区' },
|
|
|
+ ]
|
|
|
+
|
|
|
+ const matchedAlias = areaAliasMap.find(item => item.keywords.some(keyword => normalized.includes(keyword)))
|
|
|
+ return matchedAlias ? matchedAlias.value : null
|
|
|
+}
|
|
|
+
|
|
|
+const handleAutoFill = () => {
|
|
|
+ const text = normalizeText(autoFillText.value)
|
|
|
+ if (!text) {
|
|
|
+ Message.warning('请先粘贴需要识别的文本')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const studentMatch = text.match(/\b2\d{9}\b/)
|
|
|
+ const emailMatch = text.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/)
|
|
|
+ const areaMatch = matchArea(text)
|
|
|
+
|
|
|
+ let hitCount = 0
|
|
|
+
|
|
|
+ if (studentMatch?.[0]) {
|
|
|
+ form.student_num = studentMatch[0]
|
|
|
+ hitCount += 1
|
|
|
+ }
|
|
|
+ if (emailMatch?.[0]) {
|
|
|
+ form.email = emailMatch[0]
|
|
|
+ form.notice_type = 'email'
|
|
|
+ hitCount += 1
|
|
|
+ }
|
|
|
+ if (areaMatch) {
|
|
|
+ form.area = areaMatch
|
|
|
+ hitCount += 1
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hitCount === 0) {
|
|
|
+ Message.warning('未识别到可填写信息,请检查文本内容')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ Message.success(`识别成功,已填入 ${hitCount} 项信息`)
|
|
|
+}
|
|
|
+
|
|
|
const editAccount = (item) => {
|
|
|
if (item) {
|
|
|
form.id = item.id
|
|
|
@@ -543,6 +611,7 @@ const editAccount = (item) => {
|
|
|
form.notice_type = item.notice_type || 'email'
|
|
|
form.auto_day = item.auto_day
|
|
|
form.notes = item.notes
|
|
|
+ autoFillText.value = ''
|
|
|
} else {
|
|
|
form.id = null
|
|
|
form.student_num = ''
|
|
|
@@ -554,6 +623,7 @@ const editAccount = (item) => {
|
|
|
form.notice_type = 'email'
|
|
|
form.area = ''
|
|
|
form.notes = ''
|
|
|
+ autoFillText.value = ''
|
|
|
}
|
|
|
visible.value = true
|
|
|
}
|
|
|
@@ -827,4 +897,8 @@ onUnmounted(() => {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
}
|
|
|
+
|
|
|
+.auto-fill-tip {
|
|
|
+ color: rgb(var(--gray-6));
|
|
|
+}
|
|
|
</style>
|