Taio_O преди 1 месец
родител
ревизия
8709190040
променени са 5 файла, в които са добавени 81 реда и са изтрити 21 реда
  1. 20 4
      admin/config/initDb.js
  2. 2 2
      admin/controllers/groupController.js
  3. 8 8
      admin/index.js
  4. 2 2
      admin/models/Group.js
  5. 49 5
      admin/views/groups.html

+ 20 - 4
admin/config/initDb.js

@@ -1,9 +1,25 @@
+const fs = require('fs');
+const path = require('path');
 const { pool } = require('./database');
 const bcrypt = require('bcryptjs');
 const User = require('../models/User');
 
-const initDatabase = async () => {
+async function initDatabase() {
     try {
+        // 读取并执行迁移文件
+        const migrationsDir = path.join(__dirname, 'migrations');
+        const migrationFiles = fs.readdirSync(migrationsDir).sort();
+
+        for (const file of migrationFiles) {
+            if (file.endsWith('.sql')) {
+                const migrationPath = path.join(migrationsDir, file);
+                const migrationSQL = fs.readFileSync(migrationPath, 'utf8');
+                
+                console.log(`执行数据库迁移: ${file}`);
+                await pool.query(migrationSQL);
+            }
+        }
+
         // 创建数据库
         await pool.query('CREATE DATABASE IF NOT EXISTS notebot');
         await pool.query('USE notebot');
@@ -116,11 +132,11 @@ const initDatabase = async () => {
             console.log('管理员用户已存在');
         }
         
-        return true;
+        console.log('数据库初始化完成');
     } catch (error) {
-        console.error('初始化数据库失败:', error);
+        console.error('数据库初始化失败:', error);
         throw error;
     }
-};
+}
 
 module.exports = initDatabase; 

+ 2 - 2
admin/controllers/groupController.js

@@ -53,14 +53,14 @@ const createGroup = async (req, res) => {
 // @access  Private/Admin
 const updateGroup = async (req, res) => {
     try {
-        const { groupName, isActive } = req.body;
+        const { groupName, isActive, feeRate } = req.body;
         const group = await Group.findById(req.params.id);
         
         if (!group) {
             return res.status(404).json({ message: '群组不存在' });
         }
 
-        await Group.update(req.params.id, { groupName, isActive });
+        await Group.update(req.params.id, { groupName, isActive, feeRate });
         const updatedGroup = await Group.findById(req.params.id);
         res.json(updatedGroup);
     } catch (error) {

+ 8 - 8
admin/index.js

@@ -440,9 +440,9 @@ bot.onText(/\/help/, (msg) => {
 // 生成账单消息
 async function generateBillMessage(chatId) {
     try {
-        // 获取群组的最后加入时间
+        // 获取群组的最后加入时间和费率信息
         const [groupInfo] = await pool.query(
-            'SELECT last_join_time FROM groups WHERE group_id = ?',
+            'SELECT last_join_time, fee_rate FROM groups WHERE group_id = ?',
             [chatId.toString()]
         );
 
@@ -451,15 +451,16 @@ async function generateBillMessage(chatId) {
         }
 
         const lastJoinTime = groupInfo[0].last_join_time;
+        const feeRate = parseFloat(groupInfo[0].fee_rate) || 0;
 
         // 获取机器人加入后的交易记录
         const [records] = await pool.query(`
             SELECT * FROM transactions 
             WHERE group_id = ? 
-            AND time >= ?
+            AND DATE(time) = CURDATE()
             ORDER BY time DESC
             LIMIT 10
-        `, [chatId.toString(), lastJoinTime]);
+        `, [chatId.toString()]);
 
         if (!records || records.length === 0) {
             return '暂无交易记录';
@@ -470,8 +471,8 @@ async function generateBillMessage(chatId) {
         
         const totalDeposit = deposits.reduce((sum, d) => sum + parseFloat(d.amount), 0);
         const totalWithdrawal = withdrawals.reduce((sum, w) => sum + parseFloat(w.amount), 0);
-        const depositFee = totalDeposit * (process.env.DEPOSIT_FEE_RATE || 0);
-        const withdrawalFee = totalWithdrawal * (process.env.WITHDRAWAL_FEE_RATE || 0);
+        const depositFee = totalDeposit * (feeRate / 100);
+        const withdrawalFee = totalWithdrawal * (feeRate / 100);
         const remaining = totalDeposit - depositFee - totalWithdrawal - withdrawalFee;
 
         let message = `📊 *账单明细*\n\n`;
@@ -497,8 +498,7 @@ async function generateBillMessage(chatId) {
         // 添加统计信息
         message += `📈 *统计信息*\n`;
         message += `• 总入款:${totalDeposit.toFixed(2)}\n`;
-        message += `• 入款费率:${((process.env.DEPOSIT_FEE_RATE || 0) * 100).toFixed(1)}%\n`;
-        message += `• 下发费率:${((process.env.WITHDRAWAL_FEE_RATE || 0) * 100).toFixed(1)}%\n`;
+        message += `• 费率:${feeRate.toFixed(1)}%\n`;
         message += `• 应下发:${(totalDeposit - depositFee).toFixed(2)}\n`;
         message += `• 总下发:${totalWithdrawal.toFixed(2)}\n`;
         message += `• 下发单笔附加费:0.0\n`;

+ 2 - 2
admin/models/Group.js

@@ -61,8 +61,8 @@ const Group = {
     // 更新群组
     update: async (id, groupData) => {
         await pool.query(
-            'UPDATE groups SET group_name = ?, is_active = ? WHERE id = ?',
-            [groupData.groupName, groupData.isActive, id]
+            'UPDATE groups SET group_name = ?, is_active = ?, fee_rate = ? WHERE id = ?',
+            [groupData.groupName, groupData.isActive, groupData.feeRate, id]
         );
     },
 

+ 49 - 5
admin/views/groups.html

@@ -6,6 +6,7 @@
     <title>群组管理 - 后台管理系统</title>
     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
     <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet">
+    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
     <style>
         .sidebar {
             position: fixed;
@@ -115,6 +116,7 @@
                                         <th>群组ID</th>
                                         <th>群组名称</th>
                                         <th>状态</th>
+                                        <th>费率(%)</th>
                                         <th>创建时间</th>
                                         <th>操作</th>
                                     </tr>
@@ -180,6 +182,10 @@
                                 </label>
                             </div>
                         </div>
+                        <div class="mb-3">
+                            <label for="editFeeRate" class="form-label">费率 (%)</label>
+                            <input type="number" class="form-control" id="editFeeRate" step="0.1" min="0" max="100" required>
+                        </div>
                     </form>
                 </div>
                 <div class="modal-footer">
@@ -262,6 +268,7 @@
                             ${group.is_active ? '启用' : '禁用'}
                         </span>
                     </td>
+                    <td>${parseFloat(group.fee_rate || 0).toFixed(1)}%</td>
                     <td>${new Date(group.created_at).toLocaleString()}</td>
                     <td>
                         <button class="btn btn-sm btn-primary btn-action" onclick="editGroup('${group.id}')">
@@ -325,13 +332,25 @@
                     document.getElementById('editGroupId').value = group.id;
                     document.getElementById('editGroupName').value = group.group_name;
                     document.getElementById('editGroupStatus').checked = group.is_active;
+                    document.getElementById('editFeeRate').value = group.fee_rate || 0;
 
                     const modal = new bootstrap.Modal(document.getElementById('editGroupModal'));
                     modal.show();
+                } else {
+                    const data = await response.json();
+                    Swal.fire({
+                        icon: 'error',
+                        title: '加载失败',
+                        text: data.message || '加载群组信息失败'
+                    });
                 }
             } catch (error) {
                 console.error('加载群组信息失败:', error);
-                alert('加载群组信息失败,请稍后重试');
+                Swal.fire({
+                    icon: 'error',
+                    title: '加载失败',
+                    text: '加载群组信息失败,请稍后重试'
+                });
             }
         }
 
@@ -340,6 +359,16 @@
             const groupId = document.getElementById('editGroupId').value;
             const groupName = document.getElementById('editGroupName').value;
             const isActive = document.getElementById('editGroupStatus').checked;
+            const feeRate = parseFloat(document.getElementById('editFeeRate').value) || 0;
+
+            if (isNaN(feeRate) || feeRate < 0 || feeRate > 100) {
+                Swal.fire({
+                    icon: 'error',
+                    title: '输入错误',
+                    text: '费率必须在0-100之间'
+                });
+                return;
+            }
 
             try {
                 const token = localStorage.getItem('token');
@@ -349,20 +378,35 @@
                         'Authorization': `Bearer ${token}`,
                         'Content-Type': 'application/json'
                     },
-                    body: JSON.stringify({ groupName, isActive })
+                    body: JSON.stringify({ groupName, isActive, feeRate })
                 });
 
                 if (response.ok) {
                     const modal = bootstrap.Modal.getInstance(document.getElementById('editGroupModal'));
                     modal.hide();
-                    loadGroups();
+                    await loadGroups();
+                    Swal.fire({
+                        icon: 'success',
+                        title: '更新成功',
+                        text: '群组信息已更新!',
+                        timer: 1500,
+                        showConfirmButton: false
+                    });
                 } else {
                     const data = await response.json();
-                    alert(data.message || '更新群组失败');
+                    Swal.fire({
+                        icon: 'error',
+                        title: '更新失败',
+                        text: data.message || '更新群组失败'
+                    });
                 }
             } catch (error) {
                 console.error('更新群组失败:', error);
-                alert('更新群组失败,请稍后重试');
+                Swal.fire({
+                    icon: 'error',
+                    title: '更新失败',
+                    text: '更新群组失败,请稍后重试'
+                });
             }
         });