|
@@ -180,6 +180,7 @@
|
|
|
<a-doption @click="editAccount(record)"><icon-edit /> 编辑账号</a-doption>
|
|
<a-doption @click="editAccount(record)"><icon-edit /> 编辑账号</a-doption>
|
|
|
<a-doption @click="faceRecoRef.openModal(record)"><icon-video-camera /> 人脸采集</a-doption>
|
|
<a-doption @click="faceRecoRef.openModal(record)"><icon-video-camera /> 人脸采集</a-doption>
|
|
|
<a-doption @click="bindBotRef.openModal(record)"><icon-robot-add /> 绑定智能机器人</a-doption>
|
|
<a-doption @click="bindBotRef.openModal(record)"><icon-robot-add /> 绑定智能机器人</a-doption>
|
|
|
|
|
+ <a-doption @click="openBindAudit(record)"><icon-history /> 绑定解绑记录</a-doption>
|
|
|
<a-doption @click="SingleRun(record)"><icon-play-circle /> 开始单次乐跑</a-doption>
|
|
<a-doption @click="SingleRun(record)"><icon-play-circle /> 开始单次乐跑</a-doption>
|
|
|
<a-doption @click="ChangeAutoRun(record)"><icon-translate /> {{ record.auto_run ? '关闭' :
|
|
<a-doption @click="ChangeAutoRun(record)"><icon-translate /> {{ record.auto_run ? '关闭' :
|
|
|
'开启' }}自动乐跑</a-doption>
|
|
'开启' }}自动乐跑</a-doption>
|
|
@@ -243,11 +244,53 @@
|
|
|
|
|
|
|
|
<faceModal :faceInfo="faceInfo" ref="faceRecoRef" />
|
|
<faceModal :faceInfo="faceInfo" ref="faceRecoRef" />
|
|
|
<bindBot ref="bindBotRef" />
|
|
<bindBot ref="bindBotRef" />
|
|
|
|
|
+
|
|
|
|
|
+ <a-modal v-model:visible="bindAuditVisible" title="绑定解绑记录" :footer="false" width="980px" draggable>
|
|
|
|
|
+ <a-table :data="bindAuditData" :columns="bindAuditColumns" :loading="bindAuditLoading" :pagination="false"
|
|
|
|
|
+ :scroll="{ y: 420 }">
|
|
|
|
|
+ <template #lepao_user="{ record }">
|
|
|
|
|
+ <a-space>
|
|
|
|
|
+ <a-avatar :size="26">
|
|
|
|
|
+ <img :src="record.lepao_avatar || 'https://lepao-cloud.xxoo365.top/view.php/25aa126dc406974ff3579a99a2c6501a.png'" />
|
|
|
|
|
+ </a-avatar>
|
|
|
|
|
+ {{ record.lepao_name || '-' }}
|
|
|
|
|
+ </a-space>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #owner_user="{ record }">
|
|
|
|
|
+ <a-space>
|
|
|
|
|
+ <a-avatar :size="26">
|
|
|
|
|
+ <img :src="record.owner_avatar || 'https://lepao-cloud.xxoo365.top/view.php/25aa126dc406974ff3579a99a2c6501a.png'" />
|
|
|
|
|
+ </a-avatar>
|
|
|
|
|
+ {{ record.owner_username || '-' }}
|
|
|
|
|
+ </a-space>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #action="{ record }">
|
|
|
|
|
+ <a-tag>{{ actionLabel(record.action) }}</a-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #operator_user="{ record }">
|
|
|
|
|
+ <a-space>
|
|
|
|
|
+ <a-avatar :size="26">
|
|
|
|
|
+ <img :src="record.operator_avatar || 'https://lepao-cloud.xxoo365.top/view.php/25aa126dc406974ff3579a99a2c6501a.png'" />
|
|
|
|
|
+ </a-avatar>
|
|
|
|
|
+ {{ record.operator_username || '-' }}
|
|
|
|
|
+ </a-space>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #detail_json="{ record }">
|
|
|
|
|
+ {{ formatDetail(record.detail_json) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #created_at="{ record }">
|
|
|
|
|
+ {{ stramptoTime(record.created_at) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #empty>
|
|
|
|
|
+ <a-empty description="暂无绑定解绑记录" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table>
|
|
|
|
|
+ </a-modal>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { ref, reactive, onMounted, h } from 'vue'
|
|
import { ref, reactive, onMounted, h } from 'vue'
|
|
|
-import { addAccount, adminAccountList, deleteAccount, changeAutoRun, singleRun, adminUpdateAccountInfo } from '@/api/lepao'
|
|
|
|
|
|
|
+import { addAccount, adminAccountList, deleteAccount, changeAutoRun, singleRun, adminUpdateAccountInfo, getAdminBindAuditByAccount, getAdminBindAuditList } from '@/api/lepao'
|
|
|
import { Modal, Notification, Message } from '@arco-design/web-vue'
|
|
import { Modal, Notification, Message } from '@arco-design/web-vue'
|
|
|
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'
|
|
@@ -255,6 +298,9 @@ import { getSemesterTimestamps } from '@/utils/util'
|
|
|
|
|
|
|
|
const faceRecoRef = ref(null)
|
|
const faceRecoRef = ref(null)
|
|
|
const bindBotRef = ref(null)
|
|
const bindBotRef = ref(null)
|
|
|
|
|
+const bindAuditVisible = ref(false)
|
|
|
|
|
+const bindAuditLoading = ref(false)
|
|
|
|
|
+const bindAuditData = ref([])
|
|
|
|
|
|
|
|
const queryData = reactive({
|
|
const queryData = reactive({
|
|
|
area: '',
|
|
area: '',
|
|
@@ -399,6 +445,17 @@ const columns = [
|
|
|
width: 90
|
|
width: 90
|
|
|
}]
|
|
}]
|
|
|
|
|
|
|
|
|
|
+const bindAuditColumns = [
|
|
|
|
|
+ { title: '学号', dataIndex: 'student_num', width: 140 },
|
|
|
|
|
+ { title: '乐跑账号', slotName: 'lepao_user', width: 180 },
|
|
|
|
|
+ { title: '所属用户', slotName: 'owner_user', width: 180 },
|
|
|
|
|
+ { title: '动作', slotName: 'action', width: 120 },
|
|
|
|
|
+ { title: '来源', dataIndex: 'source', width: 140 },
|
|
|
|
|
+ { title: '操作者', slotName: 'operator_user', width: 180 },
|
|
|
|
|
+ { title: '详情', slotName: 'detail_json', width: 220, ellipsis: true, tooltip: true },
|
|
|
|
|
+ { title: '时间', slotName: 'created_at', width: 180 }
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
const search = () => {
|
|
const search = () => {
|
|
|
pagination.current = 1
|
|
pagination.current = 1
|
|
|
getAccounts()
|
|
getAccounts()
|
|
@@ -623,6 +680,71 @@ const UpdateAccountInfo = async (record) => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const actionLabel = (action) => {
|
|
|
|
|
+ const map = {
|
|
|
|
|
+ platform_bind: '平台绑定',
|
|
|
|
|
+ platform_unbind: '平台解绑',
|
|
|
|
|
+ bot_bind: '机器人绑定',
|
|
|
|
|
+ bot_unbind: '机器人解绑'
|
|
|
|
|
+ }
|
|
|
|
|
+ return map[action] || action
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const formatDetail = (detail) => {
|
|
|
|
|
+ if (!detail) return '-'
|
|
|
|
|
+ if (typeof detail === 'string') return detail
|
|
|
|
|
+ return Object.keys(detail).map(key => `${key}:${detail[key]}`).join(' ; ')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const openBindAudit = async (record) => {
|
|
|
|
|
+ bindAuditVisible.value = true
|
|
|
|
|
+ bindAuditLoading.value = true
|
|
|
|
|
+ bindAuditData.value = []
|
|
|
|
|
+ try {
|
|
|
|
|
+ const studentNum = String(record.student_num || '')
|
|
|
|
|
+ if (!studentNum) {
|
|
|
|
|
+ Message.warning('该账号缺少学号,无法查询审计记录')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const res = await getAdminBindAuditByAccount({
|
|
|
|
|
+ student_num: studentNum,
|
|
|
|
|
+ pagesize: 100,
|
|
|
|
|
+ current: 1
|
|
|
|
|
+ })
|
|
|
|
|
+ if (!res || res.code !== 0) {
|
|
|
|
|
+ Notification.error({
|
|
|
|
|
+ title: '获取绑定解绑记录失败',
|
|
|
|
|
+ content: res?.msg ?? '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const primaryData = Array.isArray(res.data) ? res.data : []
|
|
|
|
|
+ if (primaryData.length > 0) {
|
|
|
|
|
+ bindAuditData.value = primaryData
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const fallbackRes = await getAdminBindAuditList({
|
|
|
|
|
+ student_num: studentNum,
|
|
|
|
|
+ pagesize: 100,
|
|
|
|
|
+ current: 1
|
|
|
|
|
+ })
|
|
|
|
|
+ const fallbackData = (fallbackRes && fallbackRes.code === 0 && Array.isArray(fallbackRes.data)) ? fallbackRes.data : []
|
|
|
|
|
+ bindAuditData.value = fallbackData
|
|
|
|
|
+ if (!bindAuditData.value.length) {
|
|
|
|
|
+ Message.info('该账号暂无绑定解绑记录')
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Notification.error({
|
|
|
|
|
+ title: '获取绑定解绑记录失败',
|
|
|
|
|
+ content: error.message || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ bindAuditLoading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
queryData.queryTime = getSemesterTimestamps()
|
|
queryData.queryTime = getSemesterTimestamps()
|
|
|
getAccounts()
|
|
getAccounts()
|