Tradereads系统实现总结报告
一、实现环境
1.1 前端实现
1.1.1 体系结构
前端: vite+vue+js
前端使用 vite + vue3 + javascript作为基本框架进行web开发,采用了响应式布局,良好适配不同分辨率的屏幕,具有美观性;采用了vue的单文件组件格式,使用template进行基本布局,JavaScript为网页处理动态事件,使用tailwind css和element plus美化网页布局,实现网页布局和样式的一致性;基于VueRouter实现了前端路由跳转,无需每次从后端获取html页面,只需要通过api从后端获取少量数据,减少了IO开销,提高了网页速度;利用Pinia插件来管理全局状态,以便在整个应用程序中共享数据和状态; 集成ECharts库,以便在应用程序中创建各种图表和数据可视化,以展示信息和趋势。
在前后端交互上,项目采用前后端分离的写法,前端通过axios根据与后端约定好的api进行交互,发送和得到后端的数据并在客户端渲染,降低了前后端的耦合度。
在项目构建上,项目采用了vite来构建vue3项目。并且通过划分文件夹使得前端项目文件结构清晰,其中
api文件夹存储进行前后端交互的api方法的JavaScript文件
assets文件夹存储前端需要的静态资源,如css,img和font
components文件夹存储可复用的vue组件
locates用于国际化配置语言相关文件
router文件夹存放vue项目的路由文件
store文件夹存放保存的Pinia插件的文件,类似全局变量
utils文件夹存放了一些全局的效果配置,如点击鼠标爱心和axios等
views文件夹存放基本页面的vue文件
基于上述功能,前端实现了一个Tradereads(北航二手书交易市场)。
参考网址:孔夫子旧书网 (kongfz.com)
1.1.2 实现环境
相关依赖
启动命令:
1 2 3 4 5 # 本地运行 npm run dev # 云端运行 npm run build npm run preview
1.2 后端实现环境
后端: Ruby on Rails
Ruby on Rails 负责提供访问数据库的接口
利用 json
格式数据通过 http
协议进行前后端的交互。从前端发来的 http
请求中,根据 Route 将请求分发给不同 Controller 中,由 Controller 来与数据库进行数据存取,最后再通过 render
将包含信息的 json
数据再发送回前端
Ruby on Rails 依赖 Gemfile
1 2 3 4 5 6 7 8 9 10 ruby "3.2.2" gem "rails" , "~> 7.0.8" gem "sqlite3" , "~> 1.4" gem "puma" , "~> 5.0" gem "jbuilder" gem "tzinfo-data" , platforms: %i[ mingw mswin x64_mingw jruby ] gem "bootsnap" , require: false gem "rest-client" , "~> 2.1.0" gem 'ffi' , '~> 1.16' , '>= 1.16.3' gem 'rack-cors'
安装依赖
启动后端指令
二、系统功能结构图
2.1 用户端功能结构图
2.2 管理端功能结构图
三、基本表的定义,主外码等完整性约束定义,索引的定义
为了实现一个二手书交易网站,主要需要建立以下实体:
Users: table
列名
类型
描述
完整性约束
索引定义
id
integer
用户ID
主键约束
phone
varchar
手机号码
主键约束
right
integer
0: user 1: admin
范围约束 {0,1}
UserDetails: table
列名
类型
描述
完整性约束
索引定义
user_id
integer
用户ID
主键约束 外键约束(Users.id )
user.user_detail 指向对应 user_detail 的索引
password
varchar
密码
user_name
varchar
用户名
buy_address
text
购买地址
gender
varchar
性别 (男、女)
范围约束 {“male”,“female”}
pay_type
text
支付方式 (支付宝、微信、银行卡)
范围约束 {“alipay”,“wechat”,“card”}
avatar
varchar
头像图床地址 url
Wallets: table
列名
类型
描述
完整性约束
索引定义
user_id
integer
用户 ID
主键约束 外键约束(Users.id )
user.wallet 指向 user 对应 wallet 的索引
money_sum
decimal
商品ID
外键约束(Products.id )
Followships: table
列名
类型
描述
完整性约束
索引定义
user_id
integer
关注者
主键约束 外键约束(Users.id )
user.followers 用户的被关注列表
following_user_id
integer
被关注者
主键约束 外键约束(Users.id )
user.followings 用户的关注列表
Products: table
列名
类型
描述
完整性约束
索引定义
id
integer
商品ID
主键约束
user_id
integer
用户ID
外键约束(Users.id )
user.products 用户的销售的商品
price
decimal
价格
sell_address
text
发货地址
store
integer
库存
state
varchar
销售状态(售完/有货)
check_state
integer
0: 未审核 1: 已审核
score_per
decimal
评论平均评分
ProductDetails: table
列名
类型
描述
完整性约束
索引定义
product_id
integer
商品ID
主键约束 外键约束(Products.id )
product.product_detail 商品的详细信息
product_name
text
商品名称
product_image
varchar
商品图片
product_press
text
商品出版社
product_type
varchar
商品类型 (杂志 教科书 小说 童话 戏剧 数学 计算机 漫画 自传)
范围约束 (杂志 教科书 小说 童话 戏剧 数学 计算机 漫画 自传)
Comments: table
列名
类型
描述
完整性约束
索引定义
comment_id
integer
评价 ID
主键约束
user_id
integer
用户 ID
外键约束(Users.id )
product.comments 商品的评论
product_id
integer
商品ID
外键约束(Products.id )
user.comments 用户的评论
content
text
评价内容
score
integer
评分(从低到高有1,2,3,4,5五个等级)
范围约束(1,2,3,4,5)
created_at
datetime(6)
时间戳
Carts: table
列名
类型
描述
完整性约束
索引定义
user_id
integer
用户ID
主键约束 外键约束(Users.id )
user.carts 用户的购物车
product_id
integer
商品ID
主键约束 外键约束(Products.id )
product.carts 商品所属的购物车
number
integer
数量
addTime
datetime(6)
时间戳
Orders: table
列名
类型
描述
完整性约束
索引定义
id
integer
订单ID
主键约束
user_id
integer
购买用户ID
外键约束(Users.id )
user.orders 用户的订单
created_at
datetime(6)
订单创建时间戳
OrderItems: table
列名
类型
描述
完整性约束
索引定义
id
integer
订单项ID
主键约束
product_id
integer
商品ID
外键约束(Products.id )
product.order_items 商品所属的订单项
number
integer
数量
state
varchar
商品状态(待付款、待发货、待收货、已完成)
order_id
integer
订单ID
外键约束(Orders.id )
order.order_items 订单中含有的订单项
Notices: table
列名
类型
描述
完整性约束
索引定义
id
integer
公告 ID
主键约束
title
varchar
公告标题
notice_type
integer
公告类型 1: 系统公告,2: 关注商家上新,3: 支付提醒
范围约束(1,2,3)
user_id
integer
公告发布者 ID
外键约束(Users.id )
user.notices 用户发布的公告
NoticeRecords: table
列名
类型
描述
完整性约束
索引定义
id
integer
公告已读记录 ID
主键约束
notice_id
integer
对应公告 ID
外键约束(Notice.id )
notice.notice_records 公告的已读记录
user_id
integer
记录对应的用户 ID
外键约束(User.id )
user.notice_records 用户的已读公告记录
四、系统的安全性设计,不同人员的外模式及相关权限
4.1 系统的安全性设计
对于所有页面,当且仅当登录之后才可以进行后端的交互
管理员管理界面只有管理员身份的人员登录后才是可见状态,管理界面对普通用户不可见
4.2 不同人员的外模式及相关权限
在本应用中,人员分为两类:普通用户和管理员,对于两种人员的相关权限界定如下
普通用户权限
更改个人信息(用户名,密码,购买地址)
管理自己销售的商品
新增商品
更改书籍的库存、价格、发货地址
删除书籍
查看自己的购买订单
管理自己的销售订单
钱包功能 - 修改支付方式
管理关注列表
查看关注的用户的简要信息
取消关注
查看用户个人主页
管理员权限
所有普通用户拥有的权限
独立发布公告,所有用户可见
管理订单信息
审核商品
查看所有商品以及审核状态
修改审核状态(已审核/未审核)
五、存储过程、触发器和函数的代码说明
5.1 整体结构
在本应用中,使用 Ruby On Rails 内置的 Validations 的触发器(检查范围,类型等),机制则是在对象中检查相应字段是否满足条件,若满足条件则将该对象映射存入数据库中
TODO
5.2 触发器函数的代码说明
5.2.1 用户模块
用户的 phone
长度范围为 [3, 20],只能为数字,存在非空约束,唯一约束
用户的权限设置存在非空约束,范围为 {0,1},0 表示普通用户,1 表示管理员
1 2 3 4 5 6 7 8 class User < ApplicationRecord validates :phone , presence: true , length: { in: 3 ..20 } , numericality: { only_integer: true } , uniqueness: true validates :right , presence: true , inclusion: { in: [0 ,1 ] } end
5.2.2 用户详细信息模块
用户的用户名长度须在 [2, 10] 范围内
用户的密码存在非空约束,长度须在 [6,20] 范围内
用户的性别存在范围约束,须在 {male, female} 集合中
用户的支付方式存在范围约束,须在 {wechat, alipay, bank} 集合中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class UserDetail < ApplicationRecord validates :user_name , presence: true , length: { in: 2 ..10 , :message => "Please set your name more than 1 letters and less than 11 letters." } validates :password , presence: true validates :password , length: { in: 6 ..20 , message: "The length of password must >=6 and <=20 ." } validates :gender , inclusion: { in: %w(male female) , message: "%{value} is not available gender." } validates :pay_type , inclusion: { in: %w(wechat alipay bank) , message: "Pay type %{value} is not supported." } end
5.2.3 钱包模块
1 2 3 class Wallet < ApplicationRecord validates :money_sum , presence: true , numericality: { :greater_than_or_equal_to => 0 , :massage => "Money must be non-negative." } end
5.2.4 商品模块
商品价格有非空约束,且有范围约束,必须大于等于 0
商品发货地址有非空约束
商品库存有非空约束,且有范围约束,必须为整数且大于等于 0
商品的库存状态有范围约束,Available
:有货,StoctOut
:缺货
商品的审核状态有范围约束,0
:未审核,1
:审核已通过
1 2 3 4 5 6 7 8 9 10 11 12 13 class Product < ApplicationRecord validates :price , :presence => { massage: "Price must exist." } validates :price , numericality: { :greater_than_or_equal_to => 0 , :massage => "Price must be non-negative." } validates :sell_address , :presence => { massage: "Selladdress must exist." } validates :store , presence: true validates :store , numericality: { only_integer: true , :greater_than_or_equal_to => 0 , :massage => "Store must be non-negative." } validates :state , inclusion: { in: %w(Available StockOut) } validates :check_state , inclusion: { in: [0 , 1 ] } end
5.2.5 商品详情模块
商品名字存在非空约束且有范围约束,长度范围在 [1, 20]
商品类型存在范围约束,只能为 {杂志, 教科书, 小说, 童话, 戏剧, 数学, 计算机, 漫画, 自传}
1 2 3 4 5 class ProductDetail < ApplicationRecord validates :product_name , presence: true , length: { in: 1 ..20 } validates :product_type , inclusion: { in: %w(杂志 教科书 小说 童话 戏剧 数学 计算机 漫画 自传) } end
5.2.6 订单项模块
订单项的数量存在非空约束,且有范围约束,为纯数字且必须大于等于 1
订单项状态存在范围约束,且有范围约束 {“待支付”, “待发货”, “待收货”, “已完成”}
1 2 3 4 5 class OrderItem < ApplicationRecord validates :number , presence: true , numericality: { greater_than_or_equal_to: 1 } validates :state , presence: true , inclusion: { in: ["待支付" , "待发货" , "待收货" , "已完成" ] } end
5.2.7 公告模块
1 2 3 class Notice < ApplicationRecord validates :notice_type , presence: true , inclusion: { in: [1 , 2 ] } end
5.2.8 评论模块
评论评分存在非空约束,且有范围约束 {0, 1, 2, 3, 4, 5}
1 2 3 class Comment < ApplicationRecord validates :score , presence: true , inclusion: { in: [0 , 1 , 2 , 3 , 4 , 5 ] } end
5.3 存储过程以及对应接口
存储过程使用 Ruby On Rails 内置的 Active Record 来进行数据库存取操作
5.3.1 用户模块
注册
请求路径: /api/register
请求方法: POST
请求数据格式:
phone
:字符串格式,表示用户设置的手机号
user_name
:字符串格式,表示用户设置的用户名
gender
:字符串格式,表示用户设置的性别
password
:字符串格式,表示用户设置的密码
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"This user existed."
——用户已存在
"Register failed."
——注册失败(可能是数据不合规范)
"Register succeeded."
——注册成功
data
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 def register if User .find_by(phone: params[:phone ]) render json: response_json( false , message: RegisterError : :EXISTED_USER ) and return end user = User .new(phone: params[:phone ], right: 0 ) gender = params[:gender ] | | "male" pay_type = "alipay" user_detail = UserDetail .new(user: user, password: params[:password ], user_name: params[:user_name ], gender: gender, pay_type: pay_type) wallet = Wallet .new(user: user, money_sum: 0.0 ) if user.valid? and user_detail.valid? and wallet.valid? user.save wallet.save user_detail.save session[:current_userid ] = user.id puts "register ------------------------------ #{session[:current_userid ]} " render status: 200 , json: response_json( true , message: RegisterError : :REGISTER_SUCCESS , data: { user_id: user.id } ) else render json: response_json( false , message: RegisterError : :INVALID_INFORMATION ) end end
登录
请求路径: /api/login
请求方法: POST
请求数据格式:
phone
: 字符串格式,表示用户登录使用的手机号
password
:字符串格式,表示用户登录使用的密码
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Please enter appropriate information."
——输入的手机号或密码为空
"Password is wrong."
——密码错误
"This user is not existed."
——用户不存在
"Login succeeded."
——登录成功
data
:额外输出的信息
user_id
:表示用户名在数据库中的 id
user_name
:字符串格式,表示用户名
right
:整数格式(0 或 1),0 表示普通用户,1 表示管理员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 def login _phone = params[:phone ] _password = params[:password ] unless _phone | | _password render json: response_json( false , message: LoginError : :NO_VALID_INFORMATION_PROVIDED , ) and return end user = User .find_by(phone: params[:phone ]) unless user render json: response_json( false , message: LoginError : :USER_NOT_EXISTED ) and return end user_detail = user.user_detail unless user_detail.password == _password render json: response_json( false , message: LoginError : :WRONG_PASSWORD_PROVIDED ) and return end session[:current_userid ] = user.id puts "--------------#{session[:current_userid ]} ---------------------" render status: 200 , json: response_json( true , message: LoginError : :LOGIN_SUCCESS , data: { user_id: user.id, user_name: user_detail.user_name, right: user.right } ) end
登出
请求路径: /api/logout
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
1 2 3 4 5 6 7 def logout reset_session render status: 200 , json: response_json( true , message: Global : :SUCCESS ) end
获取用户个人信息
请求路径: /api/users/<user_id>
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Show failed."
——获取信息失败(可能是 id 不存在)
"Show succeeded."
——获取成功
data
:额外输出的信息
phone
:字符串格式,表示用户电话
user_name
:字符串格式,表示用户名
buy_address
:字符串格式,表示用户地址
gender
:字符串格式,表示用户性别
pay_type
:字符串格式,表示支付方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def show @user = User .find(params[:id ]) user = @user unless user render json: response_json( false , message: ShowError : :SHOW_FAIL ) and return end user_detail = user.user_detail render status: 200 , json: response_json( true , message: ShowError : :SHOW_SUCCEED , data: { phone: user.phone, avatar: user_detail.avatar, user_name: user_detail.user_name, buy_address: user_detail.buy_address, gender: user_detail.gender, pay_type: user_detail.pay_type, right: user.right } ) end
更改密码
请求路径: /api/users/<user_id>/modify_password
请求方法: POST
请求数据格式:
old_password
:字符串格式,表示旧密码
new_password
:字符串格式,表示新密码
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Old password was incorrect."
——旧密码错误
"Modify password failed."
——密码更改失败(可能是新密码不合规范)
"Modify password succeeded."
——更改成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 def modify_password @user = User .find(params[:user_id ]) user = @user puts "modify_password-------------#{user.id} " user_detail = user.user_detail if user_detail.password != params[:old_password ] render json: response_json( false , message: ModifyUserError : :MODIFY_PASSWORD_WRONG_PASSWORD ) else user_detail.password = params[:new_password ] if user_detail.save render status: 200 , json: response_json( true , message: ModifyUserError : :MODIFY_PASSWORD_SUCCEED ) else render json: response_json( false , message: ModifyUserError : :MODIFY_PASSWORD_FAIL ) end end end
更改用户名
请求路径: /api/users/<user_id>/modify_username
请求方法: POST
请求数据格式:
new_username
:字符串格式,表示新用户名
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Modify username succeeded."
——更改用户名成功
"Modify username failed."
——更改用户名失败
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def modify_username @user = User .find(params[:user_id ]) user = @user user_detail = user.user_detail if params[:new_username ] user_detail.user_name = params[:new_username ] end if user_detail.save render status: 200 , json: response_json( true , message: ModifyUserError : :MODIFY_USERNAME_SUCCEED ) else render json: response_json( false , message: ModifyUserError : :MODIFY_USERNAME_FAIL ) end end
更改购买地址
请求路径: /api/users/<user_id>/modify_address
请求方法: POST
请求数据格式:
new_address
:字符串格式,表示新购买地址
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Modify buy address succeeded."
——更改地址成功
"Modify buy address failed."
——更改地址失败
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def modify_address @user = User .find(params[:user_id ]) user = @user user_detail = user.user_detail if params[:new_address ] user_detail.buy_address = params[:new_address ] end if user_detail.save render status: 200 , json: response_json( true , message: ModifyUserError : :MODIFY_ADDRESS_SUCCEED ) else render json: response_json( false , message: ModifyUserError : :MODIFY_ADDRESS_FAIL ) end end
更改支付方式
请求路径: /api/users/<user_id>/modify_pay_type
请求方法: POST
请求数据格式:
new_pay_type
:字符串格式,表示新支付方式( bank
, alipay
, wechat
)
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Succeeded."
——更改地址成功
"Failed."
——更改地址失败
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def modify_pay_type @user = User .find(params[:user_id ]) user = @user user_detail = user.user_detail if params[:pay_type ] user_detail.pay_type = params[:pay_type ] end if user_detail.save render status: 200 , json: response_json( true , message: Global : :SUCCESS ) else render json: response_json( false , message: Global : :FAIL ) end end
获取所有用户列表
请求路径: /api/users
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Succeeded."
"Failed."
"Unauthorized."
data
:数组格式
users
:数组格式
user_id
:用户的id
user_phone
:字符串格式
user_name
:用户名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def index unless is_admin render json: response_json( false , message: Global : :UNAUTHORIZED ) and return end @users = User .all render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { users: @users .collect do |user | user_detail = user.user_detail { user_id: user.id, user_phone: user.phone, user_name: user_detail.user_name } end } ) end
5.3.2 商品模块
查看所有(已审核)商品
请求路径: /api/show_products
请求方法: POST
请求数据格式:
show_following
:数字格式,1:只显示已关注的用户商品,0:全部显示
show_order_base
:字符串格式, "price"或"comment"或"score"
show_order
:字符串格式, "DESC"
(降序) 或 "ASC"
(升序)
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
products
:数组类型
product_id
:商品 id
product_name
:字符串,商品名字
product_image
:字符串,商品图片地址
price
:价格
product_press
:字符串,出版社
product_type
:字符串,商品类型
seller_name
:字符串,卖家名字
sell_address
:字符串,发货地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 def show_products @products = Product .all show_following = params[:show_following ] show_order_base = params[:show_order_base ] show_order = params[:show_order ] user = current_user if show_order_base == "price" if show_order == "DESC" products = Product .order(price: :desc ) else products = Product .order(:price ) end elsif show_order_base == "comment" products = Product .all if show_order == "DESC" products = products.sort {|a, b | b.comments.length <=> a.comments.length } else products = products.sort {|a, b | a.comments.length <=> b.comments.length } end elsif show_order_base == "score" products = Product .all if show_order == "DESC" products = products.sort {|a, b | b.score_per <=> a.score_per } else products = products.sort {|a, b | a.score_per <=> b.score_per } end else products = Product .all end products = products.where(check_state: 1 ) if show_following == 1 temp = products products = [] temp.each do |product | if user.followings.include ? product.user products << product end end end render json: response_json( true , message: ShowError : :SHOW_SUCCEED , data: { products: products.collect do |product | product_detail = ProductDetail .find_by(product: product) seller = product.user { product_id: product.id, product_name: product_detail.product_name, product_image: product_detail.product_image, price: product.price, product_press: product_detail.product_press, product_type: product_detail.product_type, seller_name: seller.user_detail.user_name, sell_address: product.sell_address } end } ) end
添加商品
请求路径: /api/products
请求方法: POST
请求数据格式:
price
:浮点数,商品价格
sell_address
:字符串,发货地址
store
:整型,库存量
product_name
:字符串,商品名
product_image
:字符串,商品照片地址
product_press
:字符串,商品出版社
product_type
:字符串,书类
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Create product succeeded."
——添加成功
"Create product failed."
——添加失败
data
:额外输出信息
product_id
:数字,商品 id
state
:字符串,库存状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 def create seller = current_user price, sell_address, store = params[:price ], params[:sell_address ], params[:store ] unless price | | sell_address | | store render json: response_json( false , message: ProductError : :CREATE_FAIL ) and return end product = Product .new(user: seller, price: price, sell_address: sell_address, store: store, state: store == 0 ? "StockOut" : "Available" , check_state: 0 , score_per: 0.0 ) name, image, press, type = params[:product_name ], params[:product_image ], params[:product_press ], params[:product_type ] product_detail = ProductDetail .new(product: product, product_name: name, product_image: image, product_press: press, product_type: type) notice = Notice .new(title: "新商品上新了" , notice_type: 1 , user: seller, content: "添加了商品 #{name} " ) if product.valid? && product_detail.valid? product.save product_detail.save render status: 200 , json: response_json( true , message: ProductError : :CREATE_SUCCEED , data: { product_id: product.id, state: product.state } ) else render json: response_json( false , message: ProductError : :CREATE_FAIL ) end end
获取商品信息
请求路径: /api/products/<product_id>
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Show product succeeded."
——获取成功
"Show product failed."
——获取失败
data
:额外输出信息
product_name
:字符串格式,商品名
product_image
:图片地址
product_press
:字符串格式,商品出版社
product_price
:浮点数,商品价格
product_state
:Available
有货,StockOut
缺货
seller_name
:字符串格式,卖家用户名
seller_phone
:字符串格式,卖家联系电话
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 def show @product = Product .find(params[:id ]) product = @product unless product render json: response_json( false , message: ProductError : :SHOW_PRODUCT_FAIL ) and return end product_detail = ProductDetail .find_by(product: product) seller = User .find_by(id: product.user_id) render status: 200 , json: response_json( true , message: ProductError : :SHOW_PRODUCT_SUCCEED , data: { product_name: product_detail.product_name, product_image: product_detail.product_image, product_press: product_detail.product_press, product_price: product.price.to_f, product_state: product.state, seller_name: seller.user_detail.user_name, seller_phone: seller.phone } ) end
获取卖家商品列表
请求路径: /api/users/<user_id>/show_product_list
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Show product list succeeded."
——获取成功
"Show product list failed."
——获取失败
data
:额外输出信息
products
:数组类型,卖家的商品
product_id
:数字,商品 id
product_name
:字符串,商品名
product_image
:字符串,商品图片地址
product_store
:数字,商品库存
sell_address
:字符串,发货地址
price
:浮点数,商品价格
check_state
:false 表示商品未审核,true 表示商品审核已通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 def show_product_list @user = User .find(params[:user_id ]) user = @user unless user render json: response_json( false , message: ProductError : :SHOW_PRODUCT_LIST_FAIL ) and return end render status: 200 , json: response_json( true , message: ProductError : :SHOW_PRODUCT_LIST_SUCCEED , data: { products: user.products.collect do |product | product_detail = ProductDetail .find_by(product: product) { product_id: product.id, product_name: product_detail.product_name, product_image: product_detail.product_image, product_store: product.store, sell_address: product.sell_address, price: product.price, check_state: transfer_state(product.check_state) } end } ) end
更改库存
请求路径: /api/products/<product_id>/modify_store
请求方法: POST
请求数据格式:
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Only the seller of the product can modify."
——非卖家不可修改
"Modify store failed."
——更改失败(可能是数据不合规格)
"Modify store succeeded."
——更改成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 def modify_store @product = Product .find(params[:product_id ]) product = @product unless is_seller render json: response_json( false , message: ProductError : :MODIFY_UNAVAILABLE ) and return end new_store = params[:new_store ] product.store = new_store if new_store == 0 product.state = "StockOut" else product.state = "Available" end if product.save render status: 200 , json: response_json( true , message: ProductError : :MODIFY_STORE_SUCCEED ) else render json: response_json( false , message: ProductError : :MODIFY_STORE_FAIL ) end end
更改价格
请求路径: /api/products/<product_id>/modify_price
请求方法: POST
请求数据格式:
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Only the seller of the product can modify."
——非卖家不可修改
"Modify price failed."
——更改失败(可能是数据不合规格)
"Modify price succeeded."
——更改成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def modify_price @product = Product .find(params[:product_id ]) product = @product unless is_seller render json: response_json( false , message: ProductError : :MODIFY_UNAVAILABLE ) and return end new_price = params[:new_price ] product.price = new_price if product.save render status: 200 , json: response_json( true , message: ProductError : :MODIFY_PRICE_SUCCEED ) else render json: response_json( false , message: ProductError : :MODIFY_PRICE_FAIL ) end end
更改商品地址
请求路径: /api/products/<product_id>/modify_sell_address
请求方法: POST
请求数据格式:
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Only the seller of the product can modify."
——非卖家不可修改
"Modify sell address failed."
——更改失败(可能是数据不合规格)
"Modify sell address succeeded."
——更改成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 def modify_sell_address @product = Product .find(params[:product_id ]) product = @product puts is_seller unless is_seller render json: response_json( false , message: ProductError : :MODIFY_UNAVAILABLE ) and return end new_address = params[:new_address ] product.sell_address = new_address if product.save render status: 200 , json: response_json( true , message: ProductError : :MODIFY_ADDRESS_SUCCEED ) else render json: response_json( false , message: ProductError : :MODIFY_ADDRESS_FAIL ) end end
将商品添加到购物车
请求路径: /api/products/<product_id>/add_product_to_cart
请求方法: POST
请求数据格式:
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"There are not enough products in store."
——库存内没有足够的商品
"Add fails."
——添加失败
"Products have been added to cart."
——添加成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 def add_product_to_cart @product = Product .find(params[:product_id ]) product = @product count = params[:count ].to_i unless count >= 0 && count.is_a?(Integer ) render json: response_json( false , message: CartError : :ADD_FAIL ) and return end if count > product.store render json: response_json( false , message: CartError : :NOT_ENOUGH_STORE ) and return end product.store -= count if product.store == 0 product.state = "StockOut" end buyer = current_user cart = Cart .find_by(user: buyer, product: product) if cart cart.number += count else cart = Cart .new(user: buyer, product: product, number: count) end if cart.save render status: 200 , json: response_json( true , message: CartError : :ADD_SUCCEED ) else render json: response_json( false , message: CartError : :ADD_FAIL ) end end
直接购买商品
请求路径: /api/products/<product_id>/buy_product
请求方法: POST
请求数据格式:需要 id
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"There are not enough products in store."
——库存内没有足够的商品
"Failed."
"Succeeded."
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 def buy_product @product = Product .find(params[:product_id ]) product = @product count = params[:count ].to_i unless count >= 0 && count.is_a?(Integer ) render json: response_json( false , message: CartError : :ADD_FAIL ) and return end if count > product.store render json: response_json( false , message: CartError : :NOT_ENOUGH_STORE ) and return end product.store -= count if product.store == 0 product.state = "StockOut" end buyer = current_user order = Order .new(user: buyer) unless order.valid? render json: response_json( false , message: Global : :FAIL ) and return end state = "待支付" order_item = OrderItem .new(product: product, number: count, state: state, order: order) unless order_item.valid? render json: response_json( false , message: Global : :FAIL ) and return end order.save order_item.save render status: 200 , json: response_json( true , message: Global : :SUCCESS ) end
删除商品
请求路径: /api/products/<product_id>
请求方法: DELETE
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 def destroy @product = Product .find(params[:id ]) if @product .user == current_user or current_user.right == 1 if @product .destroy render status: 200 , json: response_json( true , message: Global : :SUCCESS ) else render json: response_json( false , message: Global : :FAIL ) end else render json: response_json( false , message: Global : :FAIL ) end end
5.3.3 购物车模块
查看当前用户的购物车
请求路径: /api/show_cart
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
total_price
:浮点数形式,购物车内总金额
products
:数组形式
product_id
:整数形式,商品 id
product_name
:字符串形式,商品名字
product_image
:字符串形式,图片地址
seller_name
:字符串形式,卖家名字
product_price
:浮点数,商品单价
product_number
:整数形式,加入购物车的该商品的数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 def show_cart user = current_user total_price = 0 user.carts.each do |cart | product = cart.product price = product.price total_price += price * cart.number end render status: 200 , json: response_json( true , message: ShowError : :SHOW_SUCCEED , data: { total_price: total_price, products: user.carts.collect do |cart | product = cart.product product_detail = ProductDetail .find_by(product: product) seller = product.user detail = seller.user_detail { product_id: product.id, product_name: product_detail.product_name, product_image: product_detail.product_image, seller_name: detail.user_name, product_price: product.price, product_number: cart.number } end } ) end
选择购物车商品加入订单
请求路径: /api/choose_cart_to_order
请求方法: GET
请求数据格式:
choose_carts
:数组形式,表示选择的购物车
返回数据格式:
success
: true
或 false
message
:错误信息字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 def choose_cart_to_order user = current_user cart_ids = params[:choose_carts ] carts = [] cart_ids.each do |cart_id | carts << Cart .find(cart_id) end puts "------------------------------#{params} " puts "-------------------------------#{carts} " order = Order .new(user: user) unless order.valid? render json: response_json( false , message: Global : :FAIL ) and return end order_items = [] carts.carts.each do |cart | state = "待支付" order_item = OrderItem .new(product: cart.product, number: cart.number, state: state, order: order) if order_item.valid? order_items << order_item else render json: response_json( false , message: Global : :FAIL ) and return end end order.save order_items.length.times do |i | carts[i].destroy order_items[i].save end render status: 200 , json: response_json( true , message: Global : :SUCCESS ) end
5.3.4 订单模块
查看当前用户的订单
请求路径: /api/show_current_orders
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
orders
:数组形式
order_id
:该订单的 id
total_price
:该订单的总金额
order_time
:字符串,该订单加入的时间
items
:数组形式,表示订单项
order_item_id
:正整数,订单项 id
product_image
:字符串,商品照片地址
product_name
:字符串,商品名字
sell_address
:字符串,发货地址
buy_num
:正整数,当前用户购买该商品的数量
product_price
:浮点数,单种商品的总价格 (数目*单价)
state
:字符串,该订单中该商品的状态
"toPay"
:待支付
"toDeliver"
:待发货
"toTake"
:待收货
"completed"
:已完成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 def show_current_orders user = current_user total_prices = [] puts user.orders.length user.orders.each do |order | total_price = 0 order.order_items.each do |item | product = item.product price = product.price total_price += price * item.number end total_prices << total_price end i = 0 render status: 200 , json: response_json( true , message: ShowError : :SHOW_SUCCEED , data: { orders: user.orders.collect do |order | i += 1 { order_id: order.id, total_price: total_prices[i-1 ], order_time: order.created_at.to_s, items: order.order_items.collect do |item | product = item.product product_detail = ProductDetail .find_by(product: product) seller = product.user seller_detail = seller.user_detail { order_item_id: item.id, product_image: product_detail.product_image, product_name: product_detail.product_name, sell_address: product.sell_address, seller_name: seller_detail.user_name, buy_num: item.number, product_price: product.price * item.number, state: item.state } end } end } ) end
查看所有平台订单(admin only)
请求路径: /api/orders
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Unauthorized."
:该用户不是管理员
"Succeeded."
data
:额外输出信息
orders
:数组形式
order_id
:该订单的 id
buyer_id
:该订单的买家 id
total_price
:该订单的总金额
order_time
:字符串,该订单加入的时间
items
:数组形式,表示订单项
order_item_id
:正整数,订单项 id
product_image
:字符串,商品照片地址
product_name
:字符串,商品名字
sell_address
:字符串,发货地址
buy_num
:正整数,当前用户购买该商品的数量
product_price
:浮点数,单种商品的总价格 (数目*单价)
state
:字符串,该订单中该商品的状态
"toPay"
:待支付
"toDeliver"
:待发货
"toTake"
:待收货
"completed"
:已完成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 def index user = current_user if user.right == 0 render json: response_json( false , message: Global : :UNAUTHORIZED ) and return end total_prices = [] Order .all.each do |order | total_price = 0 order.order_items.each do |item | product = item.product price = product.price total_price += price * item.number end total_prices << total_price end i = 0 render status: 200 , json: response_json( true , message: ShowError : :SHOW_SUCCEED , data: { orders: Order .all.collect do |order | i += 1 { order_id: order.id, buyer_id: order.user_id, total_price: total_prices[i-1 ], order_time: order.created_at.to_s, items: order.order_items.collect do |item | product = item.product product_detail = ProductDetail .find_by(product: product) seller = product.user seller_detail = UserDetail .find_by(user: seller) { order_item_id: item.id, product_image: product_detail.product_image, product_name: product_detail.product_name, sell_address: product.sell_address, seller_name: seller_detail.user_name, buy_num: item.number, product_price: product.price * item.number, state: item.state } end } end } ) end
查看当前用户销售订单项
请求路径: /api/show_sell_orders
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
order_items
:数组形式
order_id
:该订单的 id
order_item_id
:该订单项 id
order_item_number
:该订单项的商品数量
order_item_state
:该订单项的状态
product_id
:商品 id
product_name
:商品名
product_price
:商品单价
buyer_id
:买家 id
order_item_time
:订单项创建时间
order_item_total_price
:订单项总金额
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 def show_sell_orders user = current_user order_items = [] OrderItem .each do |order_item | product = order_item.product if product.user == user order_items << order_item end end puts order_items.length render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { order_items: order_items.collect do |order_item | order = order_item.order product = order_item.product { order_id: order.id, order_item_id: order_item.id, order_item_number: order_item.number, order_item_state: order_item.state, product_id: product.id, product_name: product.product_detail.product_name, product_price: product.price, buyer_id: order.user_id, order_item_time: order_item.created_at.to_s, order_item_total_price: product.price * order_item.number } end } ) end
更改订单状态
请求路径: /api/order_items/<order_item_id>/modify_order_item_state
请求方法: POST
请求数据格式:需要 id
new_state
:新状态("待支付", "待发货", "待收货", "已完成"
)
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Unauthorized."
——非卖家或管理员不可修改
"Failed."
"Succeeded."
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def modify_state item = OrderItem .find(params[:order_item_id ]) new_state = params[:new_state ] if current_user.right != 1 and current_user != item.order.user render json: response_json( false , message: Global : :UNAUTHORIZED ) and return end item.state = new_state if item.save render status: 200 , json: response_json( true , message: Global : :SUCCESS ) else render json: response_json( false , message: Global : :FAIL ) end end
删除订单(admin only)
请求路径: /api/orders/<order_id>
请求方法: DELETE
请求数据格式:无需请求数据,需要 id
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Unauthorized."
:非管理员不可操作
"Failed."
"Succeeded."
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def destroy user = current_user if user.right == 0 render json: response_json( false , message: Global : :UNAUTHORIZED ) and return end if @order .destroy render status: 200 , json: response_json( true , message: Global : :SUCCESS ) else render json: response_json( false , message: Global : :FAIL ) end end
5.3.5 审核模块
获取所有(包括未审核)商品列表
请求路径: /api/products/check_product
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Unauthorized."
:非管理员不可操作
"Failed."
"Succeeded."
data
:额外输出信息
products
:数组形式
product_id
:商品 id
product_name
:字符串,商品名字
product_image
:字符串,商品图片地址
price
:价格
product_press
:字符串,出版社
product_type
:字符串,商品类型
seller_name
:字符串,卖家名字
sell_address
:字符串,发货地址
check_state
:0 表示待审核,1 表示审核通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 def get_product_list user = current_user if user.right == 0 render json: response_json( false , message: Global : :UNAUTHORIZED ) and return end @products = Product .all products = @products render json: response_json( true , message: Global : :SUCCESS , data: { products: products.collect do |product | product_detail = ProductDetail .find_by(product: product) seller = product.user { product_id: product.id, product_name: product_detail.product_name, product_image: product_detail.product_image, price: product.price, product_press: product_detail.product_press, product_type: product_detail.product_type, seller_name: seller.user_detail.user_name, sell_address: product.sell_address, check_state: product.check_state } end } ) end
将某商品的状态设为已审核/已取消
请求路径: /api/products/<product_id>/check_product
请求方法: POST
请求数据格式:需要 id
check_result
:0 表示审核不通过(商品会删除),1 表示审核通过(商品会加到商品中心)
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Unauthorized."
:非管理员不可操作
"Failed."
"Succeeded."
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 def check_product user = current_user if user.right == 0 render json: response_json( false , message: Global : :UNAUTHORIZED ) and return end @product = Product .find(params[:product_id ]) product = @product check_result = params[:check_state ] if check_result == 0 if product.destroy render status: 200 , json: response_json( true , message: Global : :SUCCESS ) and return else render json: response_json( false , message: Global : :FAIL ) and return end end product.check_state = 1 if product.save render status: 200 , json: response_json( true , message: Global : :SUCCESS ) else render json: response_json( false , message: Global : :FAIL ) end end
5.3.6 评论模块
给某个商品添加评论
请求路径: /api/products/<product_id>/add_comment
请求方法: POST
请求数据格式:需要 id
content
:字符串,评论内容
score
:评价等级,1 到 5
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:
comment_id
:该评论的 id
date
:字符串形式,该评论的添加日期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 def add_comment @product = Product .find(params[:product_id ]) product = @product content = params[:content ] score = params[:score ].to_i product.score_per = (product.score_per * product.comments.length + score) / (product.comments.length + 1 ).to_f comment = Comment .new(product: product, user: current_user, content: content, score: score) if comment.valid? and product.valid? comment.save product.save render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { comment_id: comment.id, date: comment.created_at.to_s } ) else render json: response_json( false , message: Global : :FAIL ) end end
获得某商品的所有评论
请求路径: /api/products/<product_id>/show_comments
请求方法: GET
请求数据格式:需要 id
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
comments
:数组形式
product_id
:所属商品 id
user_id
:评论人 id
content
:评论内容
score
:评分
date
:评论创建时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def show_comments product = Product .find(params[:product_id ]) comments = product.comments render json: response_json( true , message: Global : :SUCCESS , data: { comments: comments.collect do |comment | { product_id: product.id, user_id: comment.user_id, content: comment.content, score: comment.score, date: comment.created_at.to_s } end } ) end
5.3.7 关注模块
关注用户/取关(没关注→关注,关注→取关)
请求路径: /api/users/<user_id>/follow_user
请求方法: GET
请求数据格式:无需请求数据,需要 id
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"You cannot follow yourself."
——不能关注自己
"Succeeded."
"Failed."
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 def follow_user user = User .find(params[:user_id ]) if current_user == user render json: response_json( false , message: FollowError : :CANNOT_FOLLOW_SELF ) and return end if Followship .find(user: current_user, following_user: user) followship = Followship .find(user: current_user, following_user: user) if followship.destroy render status: 200 , json: response_json( false , message: Global : :SUCCESS ) else render json: response_json( false , message: Global : :FAIL ) end end followship = Followship .new(user: current_user, following_user: user) if followship.save render status: 200 , json: response_json( false , message: Global : :SUCCESS ) else render json: response_json( false , message: Global : :FAIL ) end end
当前用户是否关注了 user_id
请求路径: /api/users/<user_id>/if_follow
请求方法: GET
请求数据格式:无需请求数据,需要 id
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
if_followed
:true 已关注,false 未关注
1 2 3 4 5 6 7 8 9 def if_follow user = User .find(params[:user_id ]) render status: 200 , json: response_json( true , message: ShowError : :SHOW_SUCCEED , data: { if_follow: (User .find(user: current_user, following_user: user) != null) }) end
获取当前用户的关注列表
请求路径: /api/users/<user_id>/follow_list
请求方法: GET
请求数据格式:无需请求数据,需要 id
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
followings
:数组形式
following_user_id
:已关注的用户 id
following_user_name
:已关注的用户名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def follow_list user = User .find(params[:user_id ]) render status: 200 , json: response_json( true , message: ShowError : :SHOW_SUCCEED , data: { followings: user.followings.collect do |following_user | following_user_detail = following_user.user_detail { following_user_id: following_user.id, following_user_name: following_user_detail.user_name } end }) end
5.3.8 公告模块
新建公告(admin only)
请求路径: /api/notices
请求方法: POST
请求数据格式:这种公告的 type
为 1
title
:字符串格式,标题
content
:字符串格式,内容
返回数据格式:
success
: true
或 false
message
:错误信息字符串
"Unauthorized."
——非管理员不可新建公告
"Succeeded."
"Failed."
data
:额外返回数据
notice_id
:该公告的 id
notice_create_time
:公告创建时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 def create if current_user.right != 1 render json: response_json( false , message: Global : :UNAUTHORIZED ) and return end user = current_user title = params[:title ] content = params[:content ] notice = Notice .new(title: title, notice_type: 1 , user: user, content: content) if notice.save render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { notice_id: notice.id, notice_create_time: notice.created_at.to_s } ) else render status: 200 , json: response_json( true , message: Global : :FAIL ) end end
查看当前用户公告
请求路径: /api/notices
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
notice
:数组形式
notice_type
:1 表示 admin 的公告,2 表示关注的用户的新商品公告
notice_user_id
:发布公告的用户 id
notice_title
:公告标题
notice_content
:公告内容
notice_create_time
:公告创建时间
notice_readed
:bool类型,公告是否已读
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 def index @notices = Notice .all user = current_user notices = [] @notices .each do |notice | if user.followings.include ? notice.user notices << notice elsif notice.user.right == 1 notices << notice end end notices.each do |notice | unless NoticeRecord .find_by(notice: notice, user: user) notice_record = NoticeRecord .new(notice: notice, user: user, readed: false ) if notice_record.valid? notice_record.save else puts("-----------notice_record save error!-------------" ) end end end render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { notices: notices.collect do |notice | notice_record = NoticeRecord .find_by(notice: notice, user: user) { notice_type: notice.notice_type, notice_user_id: notice.user_id, notice_user_name: notice.user.user_detail.user_name, notice_title: notice.title, notice_content: notice.content, notice_create_time: notice.created_at.to_s, notice_readed: notice_record.readed } end } ) notices.each do |notice | notice_record = NoticeRecord .find_by(notice: notice, user: user) notice_record.readed = true notice_record.save end end
当前用户是否有未读公告
请求路径: /api/have_new_notice
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
have_new_notice
:bool类型,有无未读公告( true
有未读的, false
没有未读的)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 def have_new_notice user = current_user @notices .each do |notice | if user.followings.include ? notice.user notice_record = NoticeRecord .find_by(notice: notice, user: user) if notice_record == null or notice_record.readed == false render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { have_new_notice: true } ) and return end elsif notice.user.right == 1 notice_record = NoticeRecord .find_by(notice: notice, user: user) if notice_record == null or notice_record.readed == false render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { have_new_notice: true } ) and return end end end render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { have_new_notice: false } ) end
5.3.9 钱包模块
查看当前用户的钱包
请求路径: /api/wallet
请求方法: GET
请求数据格式:无需请求数据
返回数据格式:
success
: true
或 false
message
:错误信息字符串
data
:额外输出信息
1 2 3 4 5 6 7 8 9 10 11 def show_wallet user = current_user wallet = user.wallet render status: 200 , json: response_json( true , message: Global : :SUCCESS , data: { money_sum: wallet.money_sum } ) end
钱包充值
请求路径: /api/wallet_charge
请求方法: POST
请求数据格式:
返回数据格式:
success
: true
或 false
message
:错误信息字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def wallet_charge charge_money = params[:charge_money ].to_f user = current_user wallet = user.wallet wallet.money_sum += charge_money if wallet.save render status: 200 , json: response_json( true , message: Global : :SUCCESS ) else render json: response_json( false , message: Global : :FAIL ) end end
六、技术和模块的论述
6.1 数据管理功能
6.1.1 基本数据管理功能
Ruby On Rails 提供了与数据库交互的接口(ActiveRecord),通过对应的数据库操作(如:where
, having
等),实现对需要的数据的新增、获取、修改、删除、打印的功能
6.1.2 系统支持 Excel 文件数据的导入
本身数据库可以导入 csv 文件存入数据库中,通过 Rails 中的 ActiveRecord 类通过触发器来剔除不合规的数据,同时数据库本身的完整性约束也在此发挥着作用
6.1.3 数据的获取
通过 python 编写自动化程序在指定网站浏览和抓取数据信息,这样操作可以模拟人的操作行为,自动进行一些重复性的任务,使获取数据和导入数据高效,并且可以实时获取信息。
利用 $requests$ 库通过 HTTP 协议请求网页,并解析网页内容,提取所需的数据。
1 2 resp = requests.get(url, headers=headers) main_page = BeautifulSoup(resp.text, "html.parser" )
使用正则表达获取想要的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 divlist = main_page.find_all("div" , class_="item clearfix" ) pattern1 = r'<a.*?>(.*?)</a>' pattern2 = r'<span.*?>(.*?)</span>' for i in divlist:name_sub = str (i.find_all("a" , class_="link" )[0 ]) s = str (i.find_all("span" , class_="text" )) result1 = re.findall(pattern1, name_sub) result2 = re.findall(pattern2, s) for x in range (len (result2)):if '/' in result2[x]:ss = result2[x].replace('/' , '' ) result2[x] = ss print (result2)name.append(result1[0 ]) author.append(result2[0 ]) press.append(result2[1 ]) time.append(result2[2 ]) if len (result2) == 4 :price.append('26.00' ) else :price.append(result2[4 ].replace('¥' ,'' )) num = (int )(random.random() * 31 ) province.append(provinces_st[num])
最后导入指定文件
1 2 3 4 5 6 7 8 9 10 11 12 data= { 'name' :name, 'author' :author, 'press' :press, 'time' :time, 'price' :price, 'province' :province } df = pd.DataFrame(data) path = './data.csv' df.to_csv(path, index=False ,encoding='utf_8_sig' )
6.2 数据展示功能
6.2.1 基本数据展示功能
前端使用 Vue+vite 将后端获取的关系表中的通过 http 协议接口发送的数据信息进行实时渲染,实现了数据的展示,同时通过后端对数据库实现的升降序数据操作来实现对数据的排序问题,而前端通过筛选的组件来实现多种条件的查询,以及对数据的翻页,跳转等功能,而且采用的是前端预处理的做法,从而避免了每次都要获取信息,降低了时间复杂度的同时不影响对功能的操作。
6.2.2 支持对数据的全文检索
前端可通过模糊搜索功能,对后端传入的视图进行模糊搜索,或者进行非模糊搜索,直接在后端进行检索能够降低时间复杂度,不需要对原数据库进行操作,便能实现这项功能
6.3 业务功能
6.3.1 基本业务功能
本应用的应用场景是二手书交易,实现了商品的购入、卖出、更改、管理,订单的查看、管理、修改、删除,购物车的加入、删除、维护、删除等功能,除此之外还实现了用户之间的关注关系,实现对指定关注用户的查看与管理,并查看对应用户的商品列表
6.3.2 支持对相关人员的业务管理
对于用户新建的商品,并不会立即传送到商品中心,而是转至管理员系统中,由管理员进行审核,只有当商品审核完之后,才能展现在商品中心;除此之外,管理员也可以对网站上所有的订单请求进行查看并更改其状态
6.4 统计分析
能够按照商品类别形成饼状图,按照各类型的数量形成比例
根据每个用户的总销售额进行排名汇总信息,以条形图的方式展现
6.5 安全防护
本应用将用户分为两类:普通用户和管理员,通过注册操作只能够注册普通用户,而管理员是应用本身就已经设置好的。普通用户不能够访问管理员界面,同样也不能够查看网站的全部订单信息、查看所有用户信息。
而对于未登录的用户,其所有功能都不会运行,因为需要有登录后的用户的 id,否则不能实现任何操作
6.6 额外技术及模块
6.6.1 前端鼠标点击特效
通过操作 DOM 元素和使用 requestAnimationFrame 或 setTimeout ,可以在页面全局范围通过javascript实现了一个页面上的爱心效果。通过监听页面点击事件,创建新的爱心元素,并使用动画效果不断更新爱心的位置、大小和透明度,从而实现随机颜色呈现在页面上的动态效果。
6.6.2 前端 404 页面的实现
从安全性角度,本应用实现了 404 页面的渲染,避免了个人中心直接网址访问
6.6.3 上传图片
对于图片的上传和访问,都通过外部 api 访问免费图床实现,对于数据量较小的本应用而言,是足以支撑正常的使用的
七、系统功能的运行实例
7.1 用户功能
7.1.1 登录/注册
提供用户名,密码,手机号等信息即可注册
输入电话,密码即可登录,登录成功即可跳转至个人中心界面
7.1.2 导航栏
导航栏可根据提示信息跳转至不同界面
7.1.3 个人中心
显示个人信息,并且点击不同按钮可选择不同功能
修改个人信息
修改用户密码
查看我的钱包
点击查看我的钱包,可查看钱包余额
点击充值即可充值余额
可以更改支付方式
查看我的购买订单
点击我的购买订单,即可查看相应订单信息
点击垃圾桶图标即可删除相应订单
点击我的销售订单,即可查看相应销售订单信息
点击修改订单状态
点击不同维度进行搜索,可模糊匹配
查看我的销售商品
点击我的销售商品,即可查看相应销售商品信息
点击编辑商品信息
查看我的关注列表
点击我的关注列表,即可查看相应关注列表信息
取消关注
查看主页,主页也可取消关注
退出登录
客服中心——提交反馈给客服
7.2 商品中心功能
导航栏点击商品中心
根据维度搜索
按照维度进行排序
可选择升序降序
立即购买/加入购物车
详细信息跳转至商品详情页/查看商家信息跳转商家详情页
个人中心页
可以发布商品
可查看类别视图
7.3 商品详情页功能
商品详细信息/商品所有评价
发布评论
7.4 购物车功能
导航栏点击购物车
添加商品到订单/看显示商品总价/清空购物车
7.5 公告功能
点击发布公告
点击公共通知
我的关注
点击我的销售,可点击查看个人中心
7.6 排行榜功能
导航栏点击排行榜
可查看今日推荐(可将推荐内容加入购物车)
可以查看商家排行榜(点击可看主页)
7.7 管理员功能
只有管理能够看到管理员界面导航
订单管理,能够查看平台所有订单详细信息,点击垃圾桶能够删除订单
审核商品,所有商品新建时会送到审核中心供管理员审核,审核通过的商品才能出现在商品中心
用户管理,能够查看平台内所有用户的信息,并且能够访问其个人主页
八、源程序简要说明
对主要数据库相关代码架构已在 五、六 模块进行了详细说明
简要概括为,本系统采用 Ruby on Rails 后端框架。 通过 http 协议与前端通信,根据路由配置将请求分发至不同ActiveController 中来执行不同的数据处理过程, 再由 ActiveController 通过 ActiveRecord 与数据库进行数据存取交互, 最后通过 http 协议将数据返回至前端
九、收获和体会
在开发二手书网站时,采用 Vue 框架作为前端技术栈,而后端则使用 Ruby,这是一个有趣而富有挑战的项目。在这个过程中每个成员的任务分工明确,避免出现任务重叠或者遗漏。可以采用敏捷开发方法,将项目分解成小任务,每个任务有明确的负责人。并且我们通过定期的会议或沟通渠道(每周一次),保持团队的信息流畅通。讨论进展、遇到的问题、解决方案等,有助于及时调整方向和解决潜在的问题。同时,任务和文档采用 notion 共享,代码通过 github 仓库管理,这有助于成员迅速融入项目,也方便日后的维护和升级。
最后大家出色的完成了任务,通过本次数据库大作业,我们不仅对 Vue 框架和 Ruby on Rails 等技术栈有了更深入的理解。学到了如何在项目中有效地应用这些技术,解决技术层面的挑战。更学到了如何更有效地沟通技术细节、解释设计决策、提出问题和解决问题。
这样的团队合作经历不仅提升了技术层面的知识和技能,也培养了团队合作的软技能,使团队更具备应对各种挑战的能力。这些经验将有助于将来的项目开发和更复杂的团队协作。