Flask+微信小程序实现Login+Profile

Python代码

首先flask的session用不了,只能用全局变量来实现。

import pymysql
from flask import Flask, request, jsonify, session
from flask_cors import CORS
from flask import make_response



app = Flask(__name__)
CORS(app, supports_credentials=True)  # 允许带上凭据(cookies)

app.secret_key = 'your_secret_key' 

# 数据库配置
db_config = {
    'host': 'localhost',
    'user': 'root',
    'password': '123456',
    'database': 'pet',
    'charset': 'utf8mb4'
}



current_user_id = None

@app.route('/login', methods=['POST'])
def login():
    global current_user_id  # 声明使用全局变量
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    
    connection = pymysql.connect(**db_config)
    try:
        with connection.cursor() as cursor:
            sql = "SELECT * FROM users WHERE username=%s AND password=%s"
            cursor.execute(sql, (username, password))
            result = cursor.fetchone()
            
            if result:
                current_user_id = result[0]  # 设置全局变量
                print(f"User ID set globally: {current_user_id}")
                return jsonify({'message': '登录成功', 'status': 'success', 'data': {'id': current_user_id, 'username': result[1]}})
            else:
                return jsonify({'message': '登录失败', 'status': 'fail'}), 401
    finally:
        connection.close()
        

@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    print("Received data:", data)  # 打印接收到的数据
    username = data.get('username')
    password = data.get('password')

    # 检查用户名和密码是否提供
    if not username or not password:
        return jsonify({'message': '用户名和密码不能为空', 'status': 'fail'}), 400
    
    connection = pymysql.connect(**db_config)
    try:
        with connection.cursor() as cursor:
            # 查询数据库以检查用户名是否已存在
            sql_check = "SELECT * FROM users WHERE username=%s"
            cursor.execute(sql_check, (username,))
            result = cursor.fetchone()
            
            if result:
                return jsonify({'message': '用户名已存在', 'status': 'fail'}), 400
            
            # 插入新用户
            sql_insert = "INSERT INTO users (username, password) VALUES (%s, %s)"
            cursor.execute(sql_insert, (username, password))
            connection.commit()

        return jsonify({'message': '注册成功', 'status': 'success'}), 201

    except pymysql.MySQLError as db_err:
        return jsonify({'message': '数据库错误', 'status': 'fail', 'error': str(db_err)}), 500
    except Exception as e:
        return jsonify({'message': '注册失败', 'status': 'fail', 'error': str(e)}), 500
    finally:
        connection.close()  # 确保连接在完成后关闭


@app.route('/profile', methods=['GET'])
def profile():
    global current_user_id  # 声明使用全局变量
    if current_user_id is None:
        return jsonify({'message': '未登录', 'status': 'fail'}), 401

    # 查询用户信息
    connection = pymysql.connect(**db_config)
    try:
        with connection.cursor() as cursor:
            sql = "SELECT username, nickname, phone, email FROM users WHERE id=%s"
            cursor.execute(sql, (current_user_id,))
            result = cursor.fetchone()

            if result:
                user_data = {
                    "username": result[0],
                    "nickname": result[1],
                    "phone": result[2],
                    "email": result[3]
                }
                return jsonify({'message': '获取成功', 'status': 'success', 'data': user_data})
            else:
                return jsonify({'message': '用户未找到', 'status': 'fail'}), 404
    finally:
        connection.close()

#==========================发布笔记===============================
@app.route('/post_note', methods=['POST'])
def post_note():
    global current_user_id
    if current_user_id is None:
        return jsonify({'message': '未登录', 'status': 'fail'}), 401

    data = request.get_json()
    print(data)
    content = data.get('content')
    

    if not content:
        return jsonify({'message': '笔记内容不能为空', 'status': 'fail'}), 400

    connection = pymysql.connect(**db_config)
    try:
        with connection.cursor() as cursor:
            sql_insert = "INSERT INTO notes (user_id, content) VALUES (%s, %s)"
            cursor.execute(sql_insert, (current_user_id, content))
            connection.commit()

        return jsonify({'message': '发布成功', 'status': 'success'}), 201

    except pymysql.MySQLError as db_err:
        return jsonify({'message': '数据库错误', 'status': 'fail', 'error': str(db_err)}), 500
    finally:
        connection.close()


# ========================== 获取笔记和评论 ===========================
@app.route('/get_note/<int:note_id>', methods=['GET'])
def get_note(note_id):
    connection = pymysql.connect(**db_config)
    try:
        with connection.cursor() as cursor:
            # 获取笔记
            sql_get_note = "SELECT content, created_at FROM notes WHERE id=%s"
            cursor.execute(sql_get_note, (note_id,))
            note = cursor.fetchone()

            if not note:
                return jsonify({'message': '笔记未找到', 'status': 'fail'}), 404

            # 获取评论
            sql_get_comments = "SELECT user_id, comment, created_at FROM comments WHERE note_id=%s"
            cursor.execute(sql_get_comments, (note_id,))
            comments = cursor.fetchall()

            return jsonify({
                'message': '获取成功',
                'status': 'success',
                'data': {
                    'content': note[0],
                    'comments': [
                        {'user_id': comment[0], 'comment': comment[1], 'created_at': comment[2]}
                        for comment in comments
                    ]
                }
            })
    except pymysql.MySQLError as db_err:
        return jsonify({'message': '数据库错误', 'status': 'fail', 'error': str(db_err)}), 500
    finally:
        connection.close()

# ========================== 提交评论 ================================
@app.route('/post_comment', methods=['POST'])
def post_comment():
    data = request.get_json()
    note_id = data.get('note_id')
    comment = data.get('comment')
    user_id = data.get('user_id')

    if not note_id or not comment or not user_id:
        return jsonify({'message': '笔记ID、评论内容和用户ID不能为空', 'status': 'fail'}), 400

    connection = pymysql.connect(**db_config)
    try:
        with connection.cursor() as cursor:
            # 检查笔记是否存在
            sql_check_note = "SELECT id FROM notes WHERE id=%s"
            cursor.execute(sql_check_note, (note_id,))
            note_exists = cursor.fetchone()

            if not note_exists:
                return jsonify({'message': '笔记不存在', 'status': 'fail'}), 404

            # 插入评论
            sql_insert_comment = "INSERT INTO comments (note_id, user_id, comment) VALUES (%s, %s, %s)"
            cursor.execute(sql_insert_comment, (note_id, user_id, comment))
            connection.commit()

        return jsonify({'message': '评论成功', 'status': 'success'}), 201

    except pymysql.MySQLError as db_err:
        return jsonify({'message': '数据库错误', 'status': 'fail', 'error': str(db_err)}), 500
    finally:
        connection.close()

#========================all_notes====展示全部笔记====================
@app.route('/get_notes', methods=['GET'])
def get_notes():
    connection = pymysql.connect(**db_config)
    try:
        with connection.cursor() as cursor:
            sql = "SELECT id, content, user_id FROM notes"  # 假设你有一个 'notes' 表存储笔记和用户ID
            cursor.execute(sql)
            notes = cursor.fetchall()
            notes_list = [{'id': note[0], 'content': note[1], 'user_id': note[2]} for note in notes]
            return jsonify({'message': '获取成功', 'status': 'success', 'data': {'notes': notes_list}})
    except pymysql.MySQLError as db_err:
        return jsonify({'message': '数据库错误', 'status': 'fail', 'error': str(db_err)}), 500
    finally:
        connection.close()




if __name__ == '__main__':
    app.run()




微信小程序代码

Login

Page({
  data: {
    username: '',
    password: ''
  },
  onUsernameInput: function(e) {
    this.setData({
      username: e.detail.value
    });
  },
  onPasswordInput: function(e) {
    this.setData({
      password: e.detail.value
    });
  },
  login: function() {
    const { username, password } = this.data;
    if (!username || !password) {
        wx.showToast({
            title: '请输入账号和密码',
            icon: 'none'
        });
        return;
    }
    wx.request({
        url: 'http://127.0.0.1:5000/login',
        method: 'POST',
        data: {
            username,
            password
        },
        success: function(res) {
            if (res.statusCode === 200) {
                const data = res.data;
                wx.showToast({
                    title: data.message,
                    icon: data.status === 'success' ? 'success' : 'none'
                });
                if (data.status === 'success') {
                    // 登录成功后,处理返回的数据
                    const userData = data.data; // 获取数组数据
                    console.log(userData); 
                    wx.redirectTo({
                      url: '/pages/index/index' 
                    });// 这里可以根据需要进行进一步处理
                    // 可以在这里进行页面跳转等操作
                }
            } else {
                wx.showToast({
                    title: '登录失败',
                    icon: 'none'
                });
            }
        },
        fail: function(err) {
            wx.showToast({
                title: '网络错误',
                icon: 'none'
            });
            console.error(err);
        }
    });
  },
  goToRegister: function() {
    wx.redirectTo({
      url: '/pages/register/register' // 修改为目标页面的路径
    });
  }
});
<view class="container">
  <view class="input-group">
    <input type="text" placeholder="请输入用户名" bindinput="onUsernameInput" />
  </view>
  <view class="input-group">
    <input type="password" placeholder="请输入密码" bindinput="onPasswordInput" />
  </view>
  <button bindtap="login">登录</button>
  <button bindtap="goToRegister">注册</button> <!-- 添加注册按钮 -->
</view>
/* 样式文件 */
.container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #f5f5f5;
  padding: 20px;
}

.input-group {
  width: 100%;
  max-width: 300px;
  margin-bottom: 20px;
}

input {
  width: 100%;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 16px;
}

button {
  width: 100%;
  max-width: 300px;
  padding: 10px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 16px;
  cursor: pointer;
}

button:hover {
  background-color: #0056b3;
}

profile

Page({
  data: {
    username: '',
    nickname: '',
    phone: '',
    email: ''
  },
  goToIndex() {
    wx.navigateTo({
      url: '/pages/index/index',  // 笔记页面的路径
    });
  },
  onLoad: function() {
    wx.request({
      url: 'http://127.0.0.1:5000/profile',
      method: 'GET',
      success: (res) => {
        if (res.statusCode === 200) {
          const data = res.data.data;
          this.setData({
            username: data.username,
            nickname: data.nickname,
            phone: data.phone,
            email: data.email
          });
        } else {
          wx.showToast({
            title: res.data.message,
            icon: 'none'
          });
        }
      },
      fail: (err) => {
        wx.showToast({
          title: '网络错误',
          icon: 'none'
        });
        console.error(err);
      }
    });
  }
});
<view class="container">
  <view class="info-section">
    <view class="info-item">
      <text>用户名:</text>
      <text>{{username}}</text>
    </view>
    <view class="info-item">
      <text>昵称:</text>
      <text>{{nickname}}</text>
    </view>
    <view class="info-item">
      <text>电话:</text>
      <text>{{phone}}</text>
    </view>
    <view class="info-item">
      <text>邮箱:</text>
      <text>{{email}}</text>
    </view>
  </view>

  <!-- 前往笔记页面的按钮 -->
  <view class="button-section">
    <button bindtap="goToIndex">返回主页</button>
  </view>
</view>
.container {
  padding: 20px;
  background-color: #f8f8f8; /* 背景颜色 */
  border-radius: 8px; /* 圆角 */
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
 
.info-section {
  margin-bottom: 20px; /* 下边距 */
}
 
.info-item {
  margin-bottom: 15px; /* 每项的下边距 */
  padding: 10px; /* 内边距 */
  background-color: #ffffff; /* 每项的背景颜色 */
  border: 1px solid #e0e0e0; /* 边框颜色 */
  border-radius: 5px; /* 边框圆角 */
  display: flex; /* 使用flex布局 */
  justify-content: space-between; /* 子项两端对齐 */
  align-items: center; /* 垂直居中对齐 */
}
 
.info-item text {
  color: #333333; /* 文本颜色 */
  font-size: 16px; /* 字体大小 */
}
 
button {
  background-color: #007aff; /* 按钮背景颜色 */
  color: white; /* 按钮文本颜色 */
  padding: 10px 15px; /* 按钮内边距 */
  border: none; /* 无边框 */
  border-radius: 5px; /* 圆角 */
  font-size: 16px; /* 字体大小 */
  cursor: pointer; /* 鼠标悬停时的光标样式 */
}
 
button:hover {
  background-color: #005bb5; /* 悬停时的背景颜色 */
}

register

Page({
  data: {
    username: '',
    password: ''
  },
  onUsernameInput: function(e) {
    this.setData({
      username: e.detail.value
    });
  },
  onPasswordInput: function(e) {
    this.setData({
      password: e.detail.value
    });
  },
  register: function() {
    const { username, password } = this.data;
    if (!username || !password) {
        wx.showToast({
            title: '请输入账号和密码',
            icon: 'none'
        });
        return;
    }
    wx.request({
        url: 'http://127.0.0.1:5000/register',
        method: 'POST',
        data: {
            username,
            password
        },
        success: function(res) {
            if (res.statusCode === 200) {
                const data = res.data;
                wx.showToast({
                    title: data.message,
                    icon: data.status === 'success' ? 'success' : 'none'
                });
                
            } else {
                wx.showToast({
                    title: '注册失败',
                    icon: 'none'
                });
            }
        },
        fail: function(err) {
            wx.showToast({
                title: '网络错误',
                icon: 'none'
            });
            console.error(err);
        }
    });
  }
});
<view class="container">
  <view class="input-group">
    <input type="text" placeholder="请输入用户名" bindinput="onUsernameInput" />
  </view>
  <view class="input-group">
    <input type="password" placeholder="请输入密码" bindinput="onPasswordInput" />
  </view>
  <button bindtap="register">注册</button>
</view>
/* 样式文件 */
.container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #f5f5f5;
  padding: 20px;
}

.input-group {
  width: 100%;
  max-width: 300px;
  margin-bottom: 20px;
}

input {
  width: 100%;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 16px;
}

button {
  width: 100%;
  max-width: 300px;
  padding: 10px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 16px;
  cursor: pointer;
}

button:hover {
  background-color: #0056b3;
}

index

Page({
  // 跳转到发布笔记页面
  goToPublishNote() {
    wx.navigateTo({
      url: '/pages/notes/notes', // 发布笔记页面的路径
    });
  },

  // 跳转到查看全部笔记页面
  goToAllNotes() {
    wx.navigateTo({
      url: '/pages/all_notes/all_notes', // 全部笔记页面的路径
    });
  },
  goToProfile() {
    wx.navigateTo({
      url: '/pages/profile/profile', // 全部笔记页面的路径
    });
  }
});
<view class="container">
  <button bindtap="goToPublishNote">发布笔记</button>
  <button bindtap="goToAllNotes">查看全部笔记</button>
  <button bindtap="goToProfile">进入个人页面</button>
</view>

all_notes

Page({
  data: {
    notes: [], // 笔记列表
  },

  // 页面加载时获取所有笔记
  onLoad() {
    this.fetchNotes();
  },

  // 获取笔记列表
  fetchNotes() {
    wx.request({
      url: 'http://127.0.0.1:5000/get_notes', // 获取笔记的后端接口
      method: 'GET',
      success: (res) => {
        if (res.data.status === 'success') {
          this.setData({ notes: res.data.data.notes });
        } else {
          wx.showToast({
            title: res.data.message,
            icon: 'none',
          });
        }
      },
      fail: () => {
        wx.showToast({
          title: '请求失败',
          icon: 'none',
        });
      },
    });
  },

  // 选择某个笔记时触发
  selectNote(event) {
    const noteId = event.currentTarget.dataset['noteId'];
    const userId = event.currentTarget.dataset['userId'];
    
    // 跳转到笔记详情页面,并传递noteId和userId作为参数
    wx.navigateTo({
      url: `/pages/note_detail/note_detail?noteId=${noteId}&userId=${userId}`,
    });
  },
});
<view class="note-list">
  <block wx:for="{{notes}}" wx:key="id">
    <view class="note-item" bindtap="selectNote" data-note-id="{{item.id}}" data-user-id="{{item.user_id}}">
      <text>笔记内容: {{item.content}}</text>
      <text>用户ID: {{item.user_id}}</text>
    </view>
  </block>
</view>

notes

Page({
  data: {
    noteContent: '',        // 发布的笔记内容
    commentContent: '',     // 评论的内容
    notes: [],              // 笔记列表
    selectedNoteId: null,   // 选中的笔记ID
    comments: []            // 当前笔记的评论列表
  },

  // 输入笔记内容
  onInputNote(event) {
    this.setData({
      noteContent: event.detail.value
    });
  },

  // 发布笔记
  postNote() {
    const { noteContent } = this.data;

    if (!noteContent) {
      wx.showToast({
        title: '笔记内容不能为空',
        icon: 'none'
      });
      return;
    }

    wx.request({
      url: 'http://127.0.0.1:5000/post_note',
      method: 'POST',
      data: {
        content: noteContent
      },
      success: (res) => {
        if (res.data.status === 'success') {
          wx.showToast({ title: '发布成功' });
          this.fetchNotes(); // 重新获取笔记列表
          this.setData({ noteContent: '' });
        } else {
          wx.showToast({ title: res.data.message, icon: 'none' });
        }
      }
    });
  },
});
<view class="container">
  <!-- 发布笔记区域 -->
  <view class="post-note">
    <textarea placeholder="请输入笔记内容" bindinput="onInputNote" value="{{noteContent}}"></textarea>
    <button bindtap="postNote">发布笔记</button>
  </view>  
</view>
.container {
  padding: 20px;
}

.post-note textarea, .post-note button {
  margin-bottom: 10px;
  width: 100%;
}

.note-list {
  margin-top: 20px;
}

.note-item {
  padding: 10px;
  background-color: #f5f5f5;
  margin-bottom: 10px;
  border-radius: 5px;
}

.comment-list {
  margin-top: 20px;
}

.comment-item {
  padding: 5px;
  background-color: #eee;
  margin-bottom: 5px;
  border-radius: 3px;
}

note_detail

Page({
  data: {
    noteId: null,
    userId: null,
    noteContent: '',
    comments: [],  // 评论列表
    newComment: '',  // 用户输入的新评论
  },

  onLoad(options) {
    const { noteId, userId } = options;
    this.setData({ noteId, userId });
    this.fetchNoteDetail(noteId);
    this.fetchComments(noteId);
  },

  // 根据noteId获取笔记详情
  fetchNoteDetail(noteId) {
    wx.request({
      url: `http://127.0.0.1:5000/get_note/${noteId}`,
      method: 'GET',
      success: (res) => {
        if (res.data.status === 'success') {
          this.setData({ noteContent: res.data.data.content });
        } else {
          wx.showToast({
            title: res.data.message,
            icon: 'none',
          });
        }
      },
      fail: () => {
        wx.showToast({
          title: '请求失败',
          icon: 'none',
        });
      },
    });
  },

  // 获取该笔记的评论
  fetchComments(noteId) {
    wx.request({
      url: `http://127.0.0.1:5000/get_comments/${noteId}`,  // 获取评论的接口
      method: 'GET',
      success: (res) => {
        if (res.data.status === 'success') {
          this.setData({ comments: res.data.data.comments });
        } else {
          wx.showToast({
            title: res.data.message,
            icon: 'none',
          });
        }
      },
      fail: () => {
        wx.showToast({
          title: '请求失败',
          icon: 'none',
        });
      },
    });
  },

  // 处理评论输入
  handleCommentInput(event) {
    this.setData({ newComment: event.detail.value });
  },

  // 提交评论
  submitComment() {
    if (!this.data.newComment.trim()) {
      wx.showToast({
        title: '请输入评论内容',
        icon: 'none',
      });
      return;
    }

    wx.request({
      url: 'http://127.0.0.1:5000/post_comment',
      method: 'POST',
      data: {
        note_id: this.data.noteId,
        comment: this.data.newComment,
        user_id: this.data.userId, // 假设使用userId代表发表评论的用户
      },
      success: (res) => {
        if (res.data.status === 'success') {
          wx.showToast({
            title: '评论成功',
          });
          // 评论成功后,重新获取评论列表
          this.fetchComments(this.data.noteId);
          this.setData({ newComment: '' });  // 清空输入框
        } else {
          wx.showToast({
            title: res.data.message,
            icon: 'none',
          });
        }
      },
      fail: () => {
        wx.showToast({
          title: '评论失败',
          icon: 'none',
        });
      },
    });
  },
});
<view class="note-detail">
  <text>笔记ID: {{noteId}}</text>
  <text>用户ID: {{userId}}</text>
  <text>笔记内容: {{noteContent}}</text>
  
  <!-- 评论部分 -->
  <view class="comments-section">
    <text>评论列表:</text>
    <block wx:for="{{comments}}" wx:key="id">
      <view class="comment-item">
        <text>用户{{item.user_id}}: {{item.comment}}</text>
      </view>
    </block>
  </view>
  
  <!-- 新增评论输入框 -->
  <view class="add-comment">
    <input type="text" placeholder="输入你的评论" value="{{newComment}}" bindinput="handleCommentInput" />
    <button bindtap="submitComment">提交评论</button>
  </view>
</view>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0wioiw0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值