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>
相关推荐
青 春 记 忆5 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO35 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO7 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白7 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲9 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)10 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机10 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor69211 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy12 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽12 小时前
真实即粗糙,光滑是伪造
人工智能·python