Browse Source

✨ feat: 新增智能机器人选项

Pchen. 2 months ago
parent
commit
b1e2e2bfc5

+ 1 - 1
.env

@@ -1,4 +1,4 @@
 NODE_ENV=production
 VITE_APP_API_BASE_URL=https://lepao-api.xxoo365.top
 VITE_RSA_PUBLIC_KEY=LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF6Z1lGYzVRMGVqbTh4akZsSjdMSQpBZDJGeC9TalM0OWQ5emwyZHlaNzNDMGZLU3Fuc1pJQUZkREpWZWV6bUp6T1hOWFdoYVZHaHFwM0dCUWVvcDBKClIxekZ3bUs1em9ReElTTDc5WVF3SmxoSjdaellhL0xNcGtGZDRDVFQ4UzUwTGFzN1FpcUtqRE1BQjFLZEpaTnIKNE5HcjNUWVV4MVVpTzlUTW9YV3lBdFZRQVN2a3lFSVFIb3B4T2Vod0ZuNGRhVE8vLzF5TXRyNnZoclE4enJRMwpxUG01YWJmY0lRM3B1WDVJd1MrekRmSkI5Rm9rc0paa3RWNHI2KzM2U1E3WGp2MDFBQjJvK20yejZqNzNuWjQ1Ci95TEx5NmZHTG5lTWpTaUxHMDhNUWFCUjV1dTNITTRnMkpnanA4eU10Rkg1Tkc5Zys1dXRhTDNzd3JGQjhxd1UKdFFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==
-VITE_APP_VERSION=1.7
+VITE_APP_VERSION=1.9

BIN
src/assets/img/qrcode.png


+ 92 - 0
src/components/BindBot/bindBot.vue

@@ -0,0 +1,92 @@
+<template>
+    <a-modal v-model:visible="visible" title="绑定智能机器人" hide-cancel mask-closable esc-to-close draggable width="auto">
+        <div class="container">
+            <div class="left">
+                <img src="../../assets/img/qrcode.png" alt="二维码" width="200">
+            </div>
+            <div class="line"></div>
+            <div class="right">
+                <div class="faceCode">
+                    <div class="title">绑定码</div>
+                    <div class="value">
+                        {{ userInfo.bind_code }}
+                    </div>
+                </div>
+                <div>
+                    <div class="title">使用方法</div>
+                    <div class="value">
+                        添加智能机器人为QQ好友,并发送“/绑定 {{ userInfo.bind_code }}”完成绑定
+                    </div>
+                </div>
+                <div v-if="userInfo.bot_account">
+                    <div class="title">绑定账号</div>
+                    <div class="value">
+                        {{ userInfo.bot_account }}
+                        <a-tag class="bindtag" color="green">
+                            <template #icon>
+                                <icon-check-circle-fill />
+                            </template>
+                            已绑定
+                        </a-tag>
+                    </div>
+                </div>
+
+            </div>
+        </div>
+    </a-modal>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+
+const visible = ref(false)
+const userInfo = ref({})
+
+const faceurl = ref('')
+
+function openModal(record) {
+    if (!record) return
+    userInfo.value = record
+    visible.value = true
+}
+
+defineExpose({ openModal })
+</script>
+
+<style lang="less" scoped>
+.container {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    gap: 20px;
+
+    .line {
+        border: 1px solid #999;
+        height: 150px;
+    }
+
+    .right {
+        display: flex;
+        flex-direction: column;
+        gap: 15px;
+
+        .title {
+            font-family: Arial, Helvetica, sans-serif;
+            font-size: 1.2em;
+            color: #666;
+            user-select: none;
+        }
+
+        .faceCode {
+            .value {
+                font-size: 2.5em;
+                font-weight: bold;
+
+                .bindtag {
+                    margin-left: 20px;
+                }
+            }
+        }
+    }
+}
+</style>

+ 21 - 5
src/pages/admin/lepaoAccount/accountList.vue

@@ -89,7 +89,7 @@
                 pageSize: pagination.pagesize,
                 current: pagination.current,
                 total: pagination.total
-            }" @page-change="handlePageChange" @page-size-change="handlePageSizeChange" >
+            }" @page-change="handlePageChange" @page-size-change="handlePageSizeChange">
                 <template #create_user="{ record }">
                     <a-avatar :size="30">
                         <img :alt="record.create_user ?? ''"
@@ -181,6 +181,13 @@
             <a-form-item field="student_num" label="学号">
                 <a-input v-model="form.student_num" placeholder="账号所有者学号,填写错误将无法登录" />
             </a-form-item>
+            <a-form-item field="notice_type" label="通知类型">
+                <a-radio-group v-model="form.notice_type">
+                    <a-radio value="email">邮件</a-radio>
+                    <a-radio value="bot">智能机器人</a-radio>
+                    <a-radio value="none">无通知</a-radio>
+                </a-radio-group>
+            </a-form-item>
             <a-form-item field="email" label="通知邮箱">
                 <a-input v-model="form.email" placeholder="用于接收乐跑失败、登录失效的通知" />
             </a-form-item>
@@ -217,6 +224,7 @@
     </a-modal>
 
     <faceModal :faceInfo="faceInfo" ref="faceRecoRef" />
+    <bindBot ref="bindBotRef" />
 </template>
 
 <script setup>
@@ -224,9 +232,12 @@ import { ref, reactive, onMounted, h } from 'vue'
 import { addAccount, adminAccountList, deleteAccount, changeAutoRun, singleRun } from '@/api/lepao'
 import { Modal, Notification, Message } from '@arco-design/web-vue'
 import faceModal from '@/components/FaceModal/faceModal.vue'
+import bindBot from '@/components/BindBot/bindBot.vue'
 import { getSemesterTimestamps } from '@/utils/util'
 
 const faceRecoRef = ref(null)
+const bindBotRef = ref(null)
+
 const queryData = reactive({
     area: '',
     student_num: '',
@@ -251,6 +262,7 @@ const form = reactive({
     student_num: '',
     email: '',
     area: '',
+    notice_type: 'email',
     auto_run: 1,
     auto_time: -1,
     target_count: 30,
@@ -421,6 +433,7 @@ const editAccount = (item) => {
         form.auto_run = item.auto_run
         form.auto_time = item.auto_time
         form.auto_day = item.auto_day
+        form.notice_type = item.notice_type || 'email'
         form.target_count = item.target_count
         form.notes = item.notes
     } else {
@@ -430,7 +443,7 @@ const editAccount = (item) => {
         form.auto_time = 7
         form.target_count = 30
         form.auto_day = [0, 1, 2, 3, 4, 5, 6]
-        form.email = email.value
+        form.email = ''
         form.notes = ''
     }
     visible.value = true
@@ -439,8 +452,8 @@ const editAccount = (item) => {
 const handleBeforeOk = async (done) => {
     try {
         ok_loading.value = true
-        const { student_num, email } = form
-        if (!student_num || !email) {
+        const { student_num, email, notice_type } = form
+        if (!student_num || (!email && notice_type === 'email')) {
             Message.error('请填写完整的账号信息')
             return false
         }
@@ -452,7 +465,7 @@ const handleBeforeOk = async (done) => {
         }
 
         const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
-        if (!emailRegex.test(email)) {
+        if (form.notice_type === 'email' && !emailRegex.test(email)) {
             Message.error('请检查邮箱格式是否正确')
             return false
         }
@@ -471,6 +484,9 @@ const handleBeforeOk = async (done) => {
         }
 
         Message.success('保存成功!')
+        if (form.notice_type === 'bot' && res.data) {
+            bindBotRef.value.openModal(res.data)
+        }
         done()
         getAccounts()
     } catch (error) {

+ 22 - 4
src/pages/lepao/accountList/index.vue

@@ -260,6 +260,7 @@
                 <template #content>
                   <a-doption @click="editAccount(record)"><icon-edit /> 编辑账号</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="SingleRun(record)"><icon-play-circle /> 开始单次乐跑</a-doption>
                   <a-doption @click="ChangeAutoRun(record)"><icon-translate /> {{ record.auto_run ? '关闭' :
                     '开启' }}自动乐跑</a-doption>
@@ -280,7 +281,14 @@
       <a-form-item field="student_num" label="学号">
         <a-input v-model="form.student_num" placeholder="账号所有者学号,填写错误将无法登录" allow-clear />
       </a-form-item>
-      <a-form-item field="email" label="通知邮箱">
+      <a-form-item field="notice_type" label="通知类型">
+        <a-radio-group v-model="form.notice_type">
+          <a-radio value="email">邮件</a-radio>
+          <a-radio value="bot">智能机器人</a-radio>
+          <a-radio value="none">无通知</a-radio>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item field="email" label="通知邮箱" v-if="form.notice_type === 'email'">
         <a-auto-complete :data="email" @search="handleSearch" v-model="form.email" placeholder="用于接收乐跑失败、登录失效的通知"
           allow-clear />
       </a-form-item>
@@ -318,6 +326,7 @@
   </a-modal>
 
   <faceModal :faceInfo="faceInfo" ref="faceRecoRef" />
+  <bindBot ref="bindBotRef" />
 </template>
 
 <script setup>
@@ -328,6 +337,7 @@ import { IconSearch } from '@arco-design/web-vue/es/icon'
 import userCard from '@/components/userCard/userCard.vue'
 import { isElectron } from '@/utils/electron'
 import faceModal from '@/components/FaceModal/faceModal.vue'
+import bindBot from '@/components/BindBot/bindBot.vue'
 import { useRoute } from 'vue-router'
 import { getNotice, getSemesterTimestamps } from '@/utils/util'
 
@@ -336,6 +346,7 @@ const notice = ref('')
 const email = ref([])
 const faceInfo = ref({})
 const faceRecoRef = ref(null)
+const bindBotRef = ref(null)
 
 const queryDataForm = reactive({
   area: '',
@@ -482,6 +493,7 @@ const form = reactive({
   area: '',
   auto_time: -1,
   auto_run: 1,
+  notice_type: 'email',
   target_count: 30,
   auto_day: [0, 1, 2, 3, 4, 5, 6],
   notes: ''
@@ -520,6 +532,7 @@ const editAccount = (item) => {
     form.auto_time = item.auto_time
     form.auto_run = item.auto_run
     form.target_count = item.target_count
+    form.notice_type = item.notice_type || 'email'
     form.auto_day = item.auto_day
     form.notes = item.notes
   } else {
@@ -530,6 +543,7 @@ const editAccount = (item) => {
     form.auto_time = -1
     form.target_count = 30
     form.auto_day = [0, 1, 2, 3, 4, 5, 6]
+    form.notice_type = 'email'
     form.area = ''
     form.notes = ''
   }
@@ -539,8 +553,8 @@ const editAccount = (item) => {
 const handleBeforeOk = async (done) => {
   try {
     ok_loading.value = true
-    const { student_num, email } = form
-    if (!student_num || !email) {
+    const { student_num, email, notice_type } = form
+    if (!student_num || (!email && notice_type === 'email')) {
       Message.error('请填写完整的账号信息')
       return false
     }
@@ -552,7 +566,7 @@ const handleBeforeOk = async (done) => {
     }
 
     const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
-    if (!emailRegex.test(email)) {
+    if (notice_type === 'email' && !emailRegex.test(email)) {
       Message.error('请检查邮箱格式是否正确')
       return false
     }
@@ -571,8 +585,12 @@ const handleBeforeOk = async (done) => {
     }
 
     Message.success('保存成功!')
+    if (form.notice_type === 'bot' && res.data) {
+      bindBotRef.value.openModal(res.data)
+    }
     done()
     getAccountsAsync()
+
   } catch (error) {
     Notification.error({
       title: '保存乐跑账号失败!',