|
@@ -148,8 +148,8 @@
|
|
|
</a-avatar>
|
|
</a-avatar>
|
|
|
</template>
|
|
</template>
|
|
|
</a-table-column>
|
|
</a-table-column>
|
|
|
- <a-table-column title="学号" :width="115" data-index="student_num" ellipsis tooltip></a-table-column>
|
|
|
|
|
- <a-table-column title="姓名" :width="130">
|
|
|
|
|
|
|
+ <a-table-column title="学号" :width="110" data-index="student_num" ellipsis tooltip></a-table-column>
|
|
|
|
|
+ <a-table-column title="姓名" :width="120">
|
|
|
<template #cell="{ record }">
|
|
<template #cell="{ record }">
|
|
|
{{ record.name ?? '请使用乐跑登录器更新账号信息' }}
|
|
{{ record.name ?? '请使用乐跑登录器更新账号信息' }}
|
|
|
</template>
|
|
</template>
|
|
@@ -167,9 +167,8 @@
|
|
|
{{ record.sex === 1 ? '男' : (record.sex === 2 ? '女' : '') }}
|
|
{{ record.sex === 1 ? '男' : (record.sex === 2 ? '女' : '') }}
|
|
|
</template>
|
|
</template>
|
|
|
</a-table-column>
|
|
</a-table-column>
|
|
|
- <a-table-column title="年级" :width="70" data-index="grade_id" tooltip></a-table-column>
|
|
|
|
|
- <a-table-column title="学院" :width="220" data-index="academy_name" tooltip></a-table-column>
|
|
|
|
|
- <a-table-column title="跑区" :width="130">
|
|
|
|
|
|
|
+ <a-table-column title="班级" :width="200" data-index="class_id" ellipsis tooltip></a-table-column>
|
|
|
|
|
+ <a-table-column title="跑区" :width="120">
|
|
|
<template #cell="{ record }">
|
|
<template #cell="{ record }">
|
|
|
{{ record.area || '随机分配' }}
|
|
{{ record.area || '随机分配' }}
|
|
|
</template>
|
|
</template>
|
|
@@ -194,19 +193,6 @@
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
</a-table-column>
|
|
</a-table-column>
|
|
|
- <!-- <a-table-column title="人脸状态" :width="100" ellipsis tooltip>
|
|
|
|
|
- <template #cell="{ record }">
|
|
|
|
|
- <div v-if="record.face_state === 0" class="state">
|
|
|
|
|
- <div class="circle zero"></div>未采集
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-else-if="record.face_state === 1" class="state">
|
|
|
|
|
- <div class="circle one"></div>已通过
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-else class="state">
|
|
|
|
|
- <div class="circle else"></div>不通过
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- </a-table-column> -->
|
|
|
|
|
<a-table-column title="自动乐跑" :width="105" ellipsis tooltip :filterable="{
|
|
<a-table-column title="自动乐跑" :width="105" ellipsis tooltip :filterable="{
|
|
|
filters: [
|
|
filters: [
|
|
|
{ text: '开启', value: 1 },
|
|
{ text: '开启', value: 1 },
|
|
@@ -215,8 +201,7 @@
|
|
|
filter: (value, record) => record.auto_run == value
|
|
filter: (value, record) => record.auto_run == value
|
|
|
}">
|
|
}">
|
|
|
<template #cell="{ record }">
|
|
<template #cell="{ record }">
|
|
|
- <a-tag color="green" v-if="record.auto_run">{{ record.target_count === 0 ? '开启-∞次' :
|
|
|
|
|
- `开启-${record.target_count}次` }}</a-tag>
|
|
|
|
|
|
|
+ <a-tag color="green" v-if="record.auto_run">开启</a-tag>
|
|
|
<a-tag color="red" v-else>关闭</a-tag>
|
|
<a-tag color="red" v-else>关闭</a-tag>
|
|
|
</template>
|
|
</template>
|
|
|
</a-table-column>
|
|
</a-table-column>
|
|
@@ -235,10 +220,19 @@
|
|
|
{{ record.auto_run ? autoTimeLabel(record) : '-' }}
|
|
{{ record.auto_run ? autoTimeLabel(record) : '-' }}
|
|
|
</template>
|
|
</template>
|
|
|
</a-table-column>
|
|
</a-table-column>
|
|
|
- <a-table-column title="学期目标" :width="88" ellipsis tooltip>
|
|
|
|
|
|
|
+ <a-table-column title="目标里程" :width="100" ellipsis tooltip>
|
|
|
<template #cell="{ record }">
|
|
<template #cell="{ record }">
|
|
|
- {{ record.term_num != record.total_num ? `${record.total_num} / ${record.term_num}` :
|
|
|
|
|
- '已完成' }}
|
|
|
|
|
|
|
+ {{ record.target_count === 0 ? '不限' : formatKm(record.target_count) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="本月里程" :width="100" ellipsis tooltip>
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ {{ formatKm(record.term_num) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="累计里程" :width="100" ellipsis tooltip>
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ {{ formatKm(record.total_num) }}
|
|
|
</template>
|
|
</template>
|
|
|
</a-table-column>
|
|
</a-table-column>
|
|
|
<a-table-column title="添加时间" :width="145" ellipsis tooltip :sortable="{
|
|
<a-table-column title="添加时间" :width="145" ellipsis tooltip :sortable="{
|
|
@@ -305,7 +299,6 @@
|
|
|
<a-option v-for="(item, index) in area" :key="index" :value="item">
|
|
<a-option v-for="(item, index) in area" :key="index" :value="item">
|
|
|
<span class="vipcontent">
|
|
<span class="vipcontent">
|
|
|
<span>{{ item }} </span>
|
|
<span>{{ item }} </span>
|
|
|
- <!-- <img src="@/assets/vip.svg" alt="vip" height="20"> -->
|
|
|
|
|
</span>
|
|
</span>
|
|
|
</a-option>
|
|
</a-option>
|
|
|
</a-select>
|
|
</a-select>
|
|
@@ -313,10 +306,11 @@
|
|
|
<a-form-item field="auto_run" label="自动乐跑开关">
|
|
<a-form-item field="auto_run" label="自动乐跑开关">
|
|
|
<a-switch v-model="form.auto_run" :checked-value="1" :unchecked-value="0" />
|
|
<a-switch v-model="form.auto_run" :checked-value="1" :unchecked-value="0" />
|
|
|
</a-form-item>
|
|
</a-form-item>
|
|
|
- <a-form-item field="target_count" label="乐跑目标次数" v-if="form.auto_run">
|
|
|
|
|
- <a-input-number v-model="form.target_count" placeholder="请输入乐跑目标次数" mode="button" />
|
|
|
|
|
|
|
+ <a-form-item field="target_count" label="目标里程(km)" 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>
|
|
<template #extra>
|
|
|
- <div>当学期有效次数达到目标次数时自动乐跑将关闭,0为不限次</div>
|
|
|
|
|
|
|
+ <div>月度里程(Km)达到目标后自动乐跑将关闭;填 0 表示不限制</div>
|
|
|
</template>
|
|
</template>
|
|
|
</a-form-item>
|
|
</a-form-item>
|
|
|
<a-form-item field="auto_day" label="自动乐跑星期" v-if="form.auto_run">
|
|
<a-form-item field="auto_day" label="自动乐跑星期" v-if="form.auto_run">
|
|
@@ -334,19 +328,26 @@
|
|
|
|
|
|
|
|
<faceModal :faceInfo="faceInfo" ref="faceRecoRef" />
|
|
<faceModal :faceInfo="faceInfo" ref="faceRecoRef" />
|
|
|
<bindBot ref="bindBotRef" />
|
|
<bindBot ref="bindBotRef" />
|
|
|
|
|
+ <SingleRunModal
|
|
|
|
|
+ v-model:visible="singleRunVisible"
|
|
|
|
|
+ :account="singleRunAccount"
|
|
|
|
|
+ @success="getAccountsAsync"
|
|
|
|
|
+ />
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { ref, reactive, onUnmounted, onMounted, h } from 'vue'
|
|
import { ref, reactive, onUnmounted, onMounted, h } from 'vue'
|
|
|
-import { accountList, deleteAccount, addAccount, changeAutoRun, singleRun, updateSelfAccount } from '@/api/lepao'
|
|
|
|
|
|
|
+import { accountList, deleteAccount, addAccount, changeAutoRun, updateSelfAccount } from '@/api/lepao'
|
|
|
import { Modal, Notification, Message } from '@arco-design/web-vue'
|
|
import { Modal, Notification, Message } from '@arco-design/web-vue'
|
|
|
import { IconSearch } from '@arco-design/web-vue/es/icon'
|
|
import { IconSearch } from '@arco-design/web-vue/es/icon'
|
|
|
import userCard from '@/components/userCard/userCard.vue'
|
|
import userCard from '@/components/userCard/userCard.vue'
|
|
|
import { isElectron } from '@/utils/electron'
|
|
import { isElectron } from '@/utils/electron'
|
|
|
import faceModal from '@/components/FaceModal/faceModal.vue'
|
|
import faceModal from '@/components/FaceModal/faceModal.vue'
|
|
|
import bindBot from '@/components/BindBot/bindBot.vue'
|
|
import bindBot from '@/components/BindBot/bindBot.vue'
|
|
|
|
|
+import SingleRunModal from '@/components/SingleRunModal/SingleRunModal.vue'
|
|
|
import { useRoute } from 'vue-router'
|
|
import { useRoute } from 'vue-router'
|
|
|
import { getNotice, getSemesterTimestamps } from '@/utils/util'
|
|
import { getNotice, getSemesterTimestamps } from '@/utils/util'
|
|
|
|
|
+import { formatKm } from '@/utils/lepaoRecord'
|
|
|
|
|
|
|
|
const notice = ref('')
|
|
const notice = ref('')
|
|
|
|
|
|
|
@@ -381,7 +382,7 @@ const pagination = reactive({
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
const handleSearch = (value) => {
|
|
const handleSearch = (value) => {
|
|
|
- const emailSuffix = ["qq.com", "ctbu.edu.cn", "163.com"]
|
|
|
|
|
|
|
+ const emailSuffix = ["qq.com", "163.com"]
|
|
|
const input = (value || "").trim()
|
|
const input = (value || "").trim()
|
|
|
|
|
|
|
|
if (!input) {
|
|
if (!input) {
|
|
@@ -408,7 +409,7 @@ const handleSearch = (value) => {
|
|
|
.map(suffix => `${prefix}@${suffix}`)
|
|
.map(suffix => `${prefix}@${suffix}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const area = ["兰花湖校区跑区", "主校区北跑区", "主校区南跑区", "重庆工商大学茶园校区"]
|
|
|
|
|
|
|
+const area = ["学府大道校区", "南山校区"]
|
|
|
const state = [
|
|
const state = [
|
|
|
{ label: '全部', value: -1 }, { label: '需登录', value: 0 }, { label: '正常', value: 1 }, { label: '状态异常', value: 2 }
|
|
{ label: '全部', value: -1 }, { label: '需登录', value: 0 }, { label: '正常', value: 1 }, { label: '状态异常', value: 2 }
|
|
|
]
|
|
]
|
|
@@ -538,7 +539,7 @@ const editAccount = (item) => {
|
|
|
form.area = item.area
|
|
form.area = item.area
|
|
|
form.auto_time = item.auto_time
|
|
form.auto_time = item.auto_time
|
|
|
form.auto_run = item.auto_run
|
|
form.auto_run = item.auto_run
|
|
|
- form.target_count = item.target_count
|
|
|
|
|
|
|
+ form.target_count = Number(item.target_count)
|
|
|
form.notice_type = item.notice_type || 'email'
|
|
form.notice_type = item.notice_type || 'email'
|
|
|
form.auto_day = item.auto_day
|
|
form.auto_day = item.auto_day
|
|
|
form.notes = item.notes
|
|
form.notes = item.notes
|
|
@@ -566,9 +567,9 @@ const handleBeforeOk = async (done) => {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const studentNumRegex = /^\d{10}$/
|
|
|
|
|
- if (!studentNumRegex.test(student_num)) {
|
|
|
|
|
- Message.error('请检查学号格式是否正确')
|
|
|
|
|
|
|
+ const sid = String(student_num || '').trim()
|
|
|
|
|
+ if (!/^[A-Za-z0-9_-]{2,64}$/.test(sid)) {
|
|
|
|
|
+ Message.error('学号/账号编码格式不正确(2–64 位字母数字下划线横线)')
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -578,6 +579,14 @@ const handleBeforeOk = async (done) => {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (form.auto_run) {
|
|
|
|
|
+ const tk = Number(form.target_count)
|
|
|
|
|
+ if (!Number.isFinite(tk) || tk < 0 || tk > 200) {
|
|
|
|
|
+ Message.error('目标里程须在 0–200 公里之间')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
let data = {
|
|
let data = {
|
|
|
...form
|
|
...form
|
|
|
}
|
|
}
|
|
@@ -649,27 +658,18 @@ const GetNotice = async () => {
|
|
|
notice.value = res
|
|
notice.value = res
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const SingleRun = async (item) => {
|
|
|
|
|
- if (item.state !== 1)
|
|
|
|
|
|
|
+const singleRunVisible = ref(false)
|
|
|
|
|
+const singleRunAccount = ref(null)
|
|
|
|
|
+
|
|
|
|
|
+const SingleRun = (item) => {
|
|
|
|
|
+ if (item.state !== 1) {
|
|
|
return Notification.warning({
|
|
return Notification.warning({
|
|
|
title: '当前乐跑账号需登录,请登录后再试',
|
|
title: '当前乐跑账号需登录,请登录后再试',
|
|
|
content: '如有疑问请联系RunForge客服'
|
|
content: '如有疑问请联系RunForge客服'
|
|
|
})
|
|
})
|
|
|
- Modal.confirm({
|
|
|
|
|
- title: '开始乐跑',
|
|
|
|
|
- content: () => h('div', [
|
|
|
|
|
- h('p', `您是否要为 ${item.name}(${item.student_num}) 乐跑?若乐跑成功将扣减乐跑次数`)
|
|
|
|
|
- ]),
|
|
|
|
|
- onOk: async () => {
|
|
|
|
|
- const res = await singleRun({ student_num: item.student_num })
|
|
|
|
|
- if (!res || res.code !== 0)
|
|
|
|
|
- return Notification.error({
|
|
|
|
|
- title: '提交乐跑任务失败',
|
|
|
|
|
- content: res?.msg ?? '请稍后再试'
|
|
|
|
|
- })
|
|
|
|
|
- Message.success('提交乐跑任务成功!')
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ singleRunAccount.value = item
|
|
|
|
|
+ singleRunVisible.value = true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const DeleteAccount = async (item) => {
|
|
const DeleteAccount = async (item) => {
|