本文回顾了我在大学期间进行的一个数据库课程设计,本课设以电费收费管理系统为题材进行开发设计。该系统主要面向电力公司管理人员和普通用户,实现电费数据管理、用电信息统计、账单生成与查询、账费核对以及用户缴费等功能。
完整文档: 基于SqlServer2012+Flask+VUE3的电费收费管理系统说明书
Github链接: 基于SqlServer2012+Flask+VUE3的电费收费管理系统
采用前后端分离BS架构,前端使用VUE框架,后端使用Flask框架,使用SQL Server数据库存储数据。
前端(VUE3) <–> API接口 <–> 后端(Flask + SQL Server)
系统主要功能包括:
根据业务需求设计ER图,主要实体包括:
根据ER图,设计关系表:
添加有效索引,提高查询性能:
系统设计了三种角色的权限控制:
CREATE TABLE Users(
UserID INT PRIMARY KEY IDENTITY, -- 用户ID,自增主键
Username VARCHAR(50) UNIQUE NOT NULL,-- 用户名,唯一,不为空
Password VARCHAR(255) NOT NULL, -- 密码,不为空
IDCard VARCHAR(18) UNIQUE NOT NULL, -- 身份证号,唯一,不为空
Role INT UNIQUE NOT NULL, -- 角色,不为空,预设可选值
RealName VARCHAR(50), -- 真实姓名
Phone VARCHAR(11), -- 电话
Email VARCHAR(50), -- 邮箱
Address VARCHAR(100), -- 地址
IsDeleted BIT DEFAULT 0 -- 软删除标志,默认未删除
)
CREATE TABLE ElectricMeter(
MeterID INT PRIMARY KEY IDENTITY, -- 电表ID,自增主键
UserID INT NOT NULL, -- 用户ID,外键引用Users(UserID)
ElecType VARCHAR(50), -- 用电类型
FOREIGN KEY (UserID) REFERENCES Users(UserID) ON DELETE CASCADE
)
CREATE TABLE ElectricityUsage(
UsageID INT PRIMARY KEY IDENTITY, -- 用电ID,自增主键
UserID INT NOT NULL, -- 用户ID,外键引用Users(UserID)
MeterID INT NOT NULL, -- 电表ID,外键引用ElectricMeter(MeterID)
Year INT NOT NULL, -- 用电年份
Month INT NOT NULL, -- 用电月份
TotalKwh DECIMAL(10,2) NOT NULL, -- 用电量(度数)
FOREIGN KEY (UserID) REFERENCES Users(UserID) ON DELETE CASCADE,
FOREIGN KEY (MeterID) REFERENCES ElectricMeter(MeterID) ON DELETE NO ACTION
)
CREATE TABLE ElectricityBill(
BillID INT PRIMARY KEY IDENTITY, -- 账单ID,自增主键
UserID INT NOT NULL, -- 用户ID,外键引用Users(UserID)
MeterID INT NOT NULL, -- 电表ID,外键引用ElectricMeter(MeterID)
ElecType VARCHAR(50) NOT NULL, -- 电费类型
Year INT NOT NULL, -- 账单年份
Month INT NOT NULL, -- 账单月份
TotalUsed DECIMAL(10,2) NOT NULL, -- 总用电量
TotalCost DECIMAL(10,2) NOT NULL, -- 总金额
PaidStatus VARCHAR(10) DEFAULT 'Unpaid', -- 付费状态
FOREIGN KEY (UserID) REFERENCES Users(UserID) ON DELETE CASCADE,
FOREIGN KEY (MeterID) REFERENCES ElectricMeter(MeterID) ON DELETE NO ACTION
)
CREATE TABLE ChargeInfo(
ChargeID INT PRIMARY KEY IDENTITY, --收费ID,自增主键
BillID INT UNIQUE NOT NULL, --账单ID,外键引用ElectricityBill(BillID)
ChargeDate DATETIME NOT NULL, --收费日期
PaidFee DECIMAL(10,2) NOT NULL, --实收金额
FOREIGN KEY (BillID) REFERENCES ElectricityBill(BillID) ON DELETE CASCADE
)
CREATE TABLE ChargeStandard(
StandardID INT PRIMARY KEY IDENTITY, -- 标准ID,自增主键
Year INT NOT NULL, -- 年份
Season INT NOT NULL, -- 季节
ElecType VARCHAR(50) NOT NULL, -- 用电类型
Price DECIMAL(10,2) NOT NULL -- 电价
)
CREATE TABLE Payment(
PaymentID INT PRIMARY KEY IDENTITY, -- 支付ID,自增主键
PayNo VARCHAR(50), -- 支付流水号
PayTime DATETIME, -- 支付时间
PayAmount DECIMAL(10,2), -- 支付金额
BillID INT UNIQUE NOT NULL, -- 账单ID,外键引用ElectricityBill(BillID)
FOREIGN KEY (BillID) REFERENCES ElectricityBill(BillID)
)
-- Users表索引
CREATE INDEX idx_username ON Users(Username)
CREATE INDEX idx_idcard ON Users(IDCard)
-- ElectricMeter表索引
CREATE UNIQUE INDEX idx_meterno ON ElectricMeter(MeterNo)
-- ElectricityUsage表索引
CREATE INDEX idx_userid_year_month ON ElectricityUsage(UserID, Year, Month)
CREATE INDEX idx_meterid_year_month ON ElectricityUsage(MeterID, Year, Month)
-- ElectricityBill表索引
CREATE INDEX idx_userid_year_month ON ElectricityBill(UserID, Year, Month)
CREATE INDEX idx_meterid_year_month ON ElectricityBill(MeterID, Year, Month)
-- ChargeInfo表索引
CREATE INDEX idx_billid ON ChargeInfo(BillID)
在Flask中使用索引无需特别调用,相关查询效率会被自动提高。
-- 管理员视图:查询所有用户
-- 创建数据库视图UserElecInfo,包含用户信息和电表信息
CREATE VIEW UserElecInfo
AS
SELECT
U.Username, U.IDCard, U.Role,
U.RealName,U.Phone, U.Email, U.Address,
EM.ElecType
FROM Users U
JOIN ElectricMeter EM ON U.UserID = EM.UserID
CREATE VIEW v_personal_info
AS
SELECT u.UserID AS User_ID, u.Username, u.RealName, u.Phone,
eb.BillID, eb.MeterID, eb.Year, eb.Month, eb.TotalUsed, eb.TotalCost, eb.PaidStatus
FROM Users u
JOIN ElectricityBill eb
ON u.UserID = eb.UserID
-- 收费员视图:查询未付费账单和用户信息
CREATE VIEW v_unpaid_bills
AS SELECT eb.*, u.Username, u.RealName, u.Phone
FROM ElectricityBill eb JOIN Users u
ON eb.UserID = u.UserID
WHERE eb.PaidStatus = 'Unpaid'
用户信息查询存储过程
CREATE PROCEDURE usp_GetUserInfo
-- @id INT修该为@user_id INT,表示用户ID
@user_id INT
AS
BEGIN
-- 添加异常处理
BEGIN TRY
SELECT
--用户名
U.Username,
--身份证号
U.IDCard,
--用户角色
U.Role,
--真实姓名
U.RealName,
--电话
U.Phone,
--邮箱
U.Email,
--地址
U.Address,
--用电类型
EM.ElecType
-- Users表与ElectricMeter表相关联,基于用户ID
FROM Users U
INNER JOIN ElectricMeter EM ON U.UserID = EM.UserID
-- 查询条件使用参数@user_id,而不硬编码
WHERE U.UserID = @user_id
END TRY
BEGIN CATCH
-- 若查询失败,则抛出自定义错误并回滚
RAISERROR('用户信息查询失败',16,1)
ROLLBACK
END CATCH
END
exec usp_GetUserInfo @user_id = 5
–用户信息更新存储过程
-- =============================================
-- Description: 更新Users与ElectricMeter表中的用户信息
-- =============================================
CREATE PROCEDURE usp_UpdateUserElecInfo
-- 用户ID,必填
@UserID INT,
-- 用户名
@Username VARCHAR(50) = NULL,
-- 真实姓名
@RealName VARCHAR(50) = NULL,
-- 电话
@Phone VARCHAR(20) = NULL,
-- 邮箱
@Email VARCHAR(50) = NULL,
-- 用电类型
@ElecType VARCHAR(50) = NULL
AS
BEGIN
-- 开启事务
BEGIN TRY
-- 若用户名不为空,更新Users表
IF @Username IS NOT NULL
UPDATE Users SET Username = @Username WHERE UserID = @UserID
-- 若真实姓名不为空,更新Users表
IF @RealName IS NOT NULL
UPDATE Users SET RealName = @RealName WHERE UserID = @UserID
-- 若电话不为空,更新Users表
IF @Phone IS NOT NULL
UPDATE Users SET Phone = @Phone WHERE UserID = @UserID
-- 若邮箱不为空,更新Users表
IF @Email IS NOT NULL
UPDATE Users SET Email = @Email WHERE UserID = @UserID
-- 若用电类型不为空,更新ElectricMeter表
IF @ElecType IS NOT NULL
UPDATE ElectricMeter SET ElecType = @ElecType
WHERE UserID = @UserID
-- 提交事务
COMMIT
END TRY
BEGIN CATCH
-- 若更新失败,则回滚并抛出自定义错误
ROLLBACK
RAISERROR('更新用户信息失败',16,1)
END CATCH
END
– 管理员存储过程:账单生成
CREATE PROC usp_generate_bill
@Year INT, -- 指定年份
@Month INT -- 指定月份
AS
-- 生成指定年月的电费账单
INSERT INTO ElectricityBill(UserID, MeterID, ElecType, Year, Month,
TotalUsed, TotalCost, PaidStatus)
SELECT
Users.UserID, -- 用户ID
ElectricMeter.MeterID, -- 电表ID
ElectricMeter.ElecType, -- 用电类型
@Year, -- 用电年份
@Month, -- 用电月份
SUM(ElectricityUsage.TotalKwh),-- 总用电量
(SELECT Price FROM ChargeStandard -- 查询当月电价
WHERE ElecType = ElectricMeter.ElecType AND
Year = @Year AND
--计算当前Season
Season = (@Month-1)/3 + 1) * SUM(ElectricityUsage.TotalKwh), -- 总金额
'Unpaid' -- 未付费状态
FROM Users
LEFT JOIN ElectricityUsage
ON Users.UserID = ElectricityUsage.UserID
LEFT JOIN ElectricMeter
ON ElectricityUsage.MeterID = ElectricMeter.MeterID
WHERE Year = @Year AND Month = @Month
GROUP BY Users.UserID,ElectricMeter.MeterID,ElectricMeter.ElecType
-- 计算当前Season(季节)
-- Spring: 3,4,5 Season = 1
-- Summer: 6,7,8 Season = 2
-- Autumn: 9,10,11 Season = 3
-- Winter: 12,1,2 Season = 4
– 收费员存储过程:手工收费
CREATE PROC usp_manual_charge
@BillID int,
@PaidFee money
AS
BEGIN
SET NOCOUNT ON;
-- 定义自定义错误
DECLARE @ErrMsg nvarchar(50) = 'Payment record already exists.'
-- 开始事务
BEGIN TRY
BEGIN TRAN
-- 判断ChargeInfo表是否已存在该账单的支付记录
IF EXISTS (SELECT * FROM ChargeInfo WHERE BillID = @BillID)
BEGIN
THROW 50000, @ErrMsg, 1
END
-- 判断Payment表是否已存在该账单的支付记录
IF EXISTS (SELECT * FROM Payment WHERE BillID = @BillID)
BEGIN
THROW 50000, @ErrMsg, 1
END
-- 更新账单状态为"已付清"
UPDATE ElectricityBill
SET PaidStatus = 'Paid'
WHERE BillID = @BillID
-- 事务提交
COMMIT TRAN
END TRY
-- 回滚事务
BEGIN CATCH
ROLLBACK TRAN
END CATCH
-- 插入收费信息记录
INSERT INTO ChargeInfo(BillID, ChargeDate, PaidFee)
VALUES(@BillID, GETDATE(), @PaidFee)
-- 插入支付信息记录
INSERT INTO Payment(BillID, PayTime, PayAmount)
VALUES(@BillID, GETDATE(), @PaidFee)
END
python-flask调用管理员存储过程
db.session.execute(‘EXEC usp_generate_bills’)
python-flask收费员存储过程
db.session.execute(‘EXEC usp_manual_charge @BillID=?, @PaidFee=?’, [bill_id, paid_fee])
-- 创建一个名为 tr_create_user_electric_meter 的触发器
CREATE TRIGGER tr_create_user_electric_meter
-- 指定在 Users 表中插入数据时触发此操作
ON Users
AFTER INSERT
AS
BEGIN
-- 在插入操作后,将新的 UserID 添加到 ElectricMeter 表中
INSERT INTO ElectricMeter (UserID)
SELECT i.UserID
FROM inserted AS i
-- 确保仅为Meter 表中不存在的 UserID 添加新记录
WHERE NOT EXISTS (
SELECT 1
FROM ElectricMeter AS em
WHERE em.UserID = i.UserID
)
END;
CREATE TRIGGER trg_delete_user_info
ON Users
FOR DELETE
AS
BEGIN
DELETE FROM ElectricMeter
WHERE UserID IN (SELECT UserID FROM DELETED)
DELETE FROM ElectricityUsage
WHERE UserID IN (SELECT UserID FROM DELETED)
DELETE FROM ElectricityBill
WHERE UserID IN (SELECT UserID FROM DELETED)
END
--在账单付费时,自动更新账单的付费状态为“已付费”:
CREATE TRIGGER trg_update_bill_status
ON ChargeInfo
FOR INSERT
AS
BEGIN
UPDATE ElectricityBill
SET PaidStatus = 'Paid'
WHERE BillID IN (SELECT BillID FROM INSERTED)
END
@app.route('/users/register', methods=['POST'])
def create_user():
username = request.json.get('Username')
password = request.json.get('Password')
idcard = request.json.get('IDCard')
if not all([username, password, idcard]):
return jsonify(errno=4001, errmsg='参数不完整')
if Users.query.filter(Users.Username == username).first():
return jsonify(errno=3001, errmsg='用户名 {} 已存在'.format(username))
if Users.query.filter(Users.IDCard == idcard).first():
return jsonify(errno=3002, errmsg='身份证号 {} 已存在'.format(idcard))
role = 3 # 默认role从3开始
# 判断role是否唯一
while Users.query.filter_by(Role=role).first():
role += 1 # 如果角色存在,递增role值
# 校验输入
# 加密密码
hash_pw = generate_password_hash(password)
# 添加用户
user = Users(Username=username, Password=hash_pw, Role=role, IDCard=idcard)
try:
# 添加用户并提交
db.session.add(user)
# 在插入用户前禁用触发器
db.session.execute(text("ALTER TABLE Users DISABLE TRIGGER tr_create_user_electric_meter"))
db.session.commit()
# 获取刚刚插入的用户的 UserID
inserted_user = Users.query.filter_by(Username=username).first()
if inserted_user:
# 添加电表记录并提交
electric_meter = ElectricMeter(UserID=inserted_user.UserID)
db.session.add(electric_meter)
db.session.commit()
# 在插入用户后启用触发器
db.session.execute(text("ALTER TABLE Users ENABLE TRIGGER tr_create_user_electric_meter"))
db.session.commit()
return jsonify(status='success', msg='用户注册成功')
except Exception as e:
db.session.rollback()
return jsonify(status='error', msg='用户注册失败:{}'.format(str(e)))
@app.route('/login', methods=['POST'])
def login():
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
# JSON 校验
username = request.json.get('Username', None) # 获取请求中的用户名
password = request.json.get('Password', None) # 获取请求中的密码
user = Users.query.filter_by(Username=username).first()
print(username, password)
# 登录校验
if not user or not check_password_hash(user.Password, password):
print('用户名或密码错误')
return jsonify(errno=RET.DATAERR, errmsg='用户名或密码错误')
# 访问令牌黑名单校验
if cache.get(access_token_blacklist_key.format(user.UserID)):
# 清除用户登录信息缓存
cache.delete(user_info_key.format(user.UserID))
# 设置登录Session过期
session.pop(user.UserID, None)
if user and check_password_hash(user.Password, password):
login_user(user)
# 生成访问和刷新token
access_token = create_access_token(identity=user.UserID, additional_claims={'privilege': user.Role},
expires_delta=timedelta(minutes=30))
# 生成刷新令牌
refresh_token = create_refresh_token(identity=user.UserID, expires_delta=timedelta(days=7))
# 存储用户登录信息至缓存
cache.set(user_info_key.format(user.UserID), user, timeout=30 * 24 * 60 * 60)
print('登陆成功')
return jsonify(access_token=access_token, refresh_token=refresh_token), 200
else:
return jsonify({"msg": "Bad username or password"}), 401
@app.route('/logout', methods=['POST'])
@jwt_required()
def logout():
"""用户登出"""
user_id = get_jwt_identity()
# 校验是否在黑名单中,如果在,则表示已经退出,直接返回
if cache.get(access_token_blacklist_key.format(user_id)):
return jsonify(errno=RET.OK, errmsg='已登出')
# 如果不在,则退出登录
# 删除用户登录缓存中的信息
cache.delete(user_info_key.format(user_id))
# 设置登录session过期
session.pop(user_id, None)
# 清空访问令牌缓存
cache.delete(access_token_blacklist_key.format(user_id))
# 记录日志
current_app.logger.info('用户 {} 登出'.format(user_id))
# 将access token加入黑名单
cache.set(access_token_blacklist_key.format(user_id), 1, timeout=60)
# 返回成功信息
logout_user()
return jsonify(errno=RET.OK, errmsg='退出成功')
@app.route('/profile')
@jwt_required()
def get_user_profile():
user_id = get_jwt_identity()
current_app.logger.debug('用户 %s 访问个人信息接口', user_id)
result = db.session.execute(text(f'EXEC usp_GetUserInfo @user_id = {user_id}'))
data = []
for row in result:
# 直接转为字典,不需要排序
d = {col: val for col, val in zip(result.keys(), row)}
data.append(d)
db.session.commit()
return jsonify(data)
@app.route('/profile/update', methods=['PUT'])
@jwt_required()
def update_profile():
u_id = get_jwt_identity()
data = request.get_json()
username = data.get('Username')
real_name = data.get('RealName')
phone = data.get('Phone')
email = data.get('Email')
elec_type = data.get('ElecType')
sql = f'EXEC usp_UpdateUserElecInfo @UserID = {u_id}'
if username is not None:
sql = sql + f', @Username = {username}'
elif real_name is not None:
sql = sql + f', @RealName = {real_name}'
elif phone is not None:
sql = sql + f', @Phone = {phone}'
elif email is not None:
sql = sql + f', @Email = {email}'
elif elec_type is not None:
sql = sql + f', @ElecType = {elec_type}'
db.session.execute(text(sql))
db.session.commit() # 手动提交事务
user = Users.query.get(u_id)
users_data = UsersSchema().dump(user)
return jsonify(users_data)
def admin_required():
def decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
try:
token = request.headers.get('Authorization').split(' ')[1]
print(token)
except:
return jsonify(errno=RET.ROLEERR, errmsg='token error'), 401
try:
claims = jwtt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
print(claims)
except:
return jsonify(errno=RET.ROLEERR, errmsg='claims error'), 401
role = claims['privilege']
if role != 0: # ROLE = {0: '管理员'}
return jsonify(errno=RET.ROLEERR, errmsg='用户权限不足'), 401
try:
return fn(*args, **kwargs)
except DatabaseError:
return '数据库异常,请稍后再试。', 500
return wrapper
return decorator
def admin_or_charger_required():
def decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
token = request.headers.get('Authorization').split(' ')[1]
claims = jwtt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
role = claims['privilege']
if role > 1:
return jsonify(errno=RET.ROLEERR, errmsg='用户权限不足'), 401
try:
return fn(*args, **kwargs)
except DatabaseError:
return '数据库异常,请稍后再试。', 500
return wrapper
return decorator
@app.route('/bills', methods=['POST'])
@admin_or_charger_required()
def generate_bill():
# 获取参数
year = request.json.get('year')
month = request.json.get('month')
# 校验参数
if not year or not month:
abort(400, description='The year and month are required!')
# 调用存储过程生成账单
db.session.execute('CALL usp_generate_bill(:year, :month)', {'year': year, 'month': month})
db.session.commit()
# 返回成功
return jsonify(errno=RET.OK, errmsg='生成成功')
@app.route('/bills')
@jwt_required()
def query_bill():
# 获取参数
u_id = current_user.get_id()
# 查询账单
bills = ElectricityBill.query.filter_by(PaidStatus='Unpaid', UserID=u_id).all()
result = ElectricityBillSchema(many=True).dump(bills)
# 额外返回每个账单的BillID
for bill in result:
bill['bill_id'] = bill.pop('BillID')
print(bill['bill_id'])
# 返回账单
return jsonify(errno=RET.OK, errmsg='OK', data=result)
@app.route('/payments', methods=['POST'])
@jwt_required()
def make_payment():
# 获取参数
bill_id = request.json.get('billid')
# 插入支付记录
bill = ElectricityBill.query.get(bill_id)
# 支付相关逻辑...
pay_no = '#1234' # 支付流水号
pay_time = datetime.now() # 支付时间
pay_amount = bill.TotalCost # 支付金额
# 写入Payment表
payment = Payment(PayNo=pay_no, PayTime=pay_time, PayAmount=pay_amount, BillID=bill_id)
db.session.add(payment)
db.session.add()
bill.PaidStatus = 'Paid'
db.session.commit()
# 返回支付记录ID
return jsonify(errno=RET.OK, errmsg='支付成功')
@app.route('/clerk/unpaid_bills')
@admin_or_charger_required() # 自定义装饰器检查收费员权限
def get_unpaid_bills():
# 获取待收费账单
bills = ElectricityBill.query.filter_by(PaidStatus='Unpaid').all()
result = ElectricityBillSchema(many=True).dump(bills)
result2 = db.session.execute('SELECT * FROM v_unpaid_bills')
return jsonify(errno=RET.OK, errmsg='成功', data=result)
@app.route('/clerk/charge', methods=['POST'])
@admin_or_charger_required()
def charge_bill():
# 收费员选择账单并输入实收金额
bill_id = request.json.get('bill_id')
paid_fee = request.json.get('paid_fee')
# 执行存储过程完成收费操作
db.session.execute('CALL usp_manual_charge(:bill_id, :paid_fee)', {'bill_id': bill_id, 'month': paid_fee})
db.session.commit()
return jsonify(errno=RET.OK, errmsg='收费成功')
python-flask-vue-web
|- app.py Flask入口文件,启动Flask
|- static 存放Vue build后的静态资源文件夹
|- templates 存放Vue build后的index.html文件
|- vue-web Vue前端项目主目录
vue-web
|- node_modules 项目依赖包文件夹
|- public
| |- index.html
| |- static 存放第三方js和favicon.ico
|- src Vue源码目录
| |- api.js 定义接口api规则
| |- assets 资源文件夹
| |- components 组件文件夹
| |- router 路由文件夹
| | |- index.js 配置路由规则和视图映射
| |- views 视图/页面文件夹
| | |- HomePage.vue
| | |- UserLogin.vue
| | |- UserProfile.vue
| | |- UserRegister.vue
| | |- HomePage.vue
…
| |- App.vue 根组件
| |- main.js 入口文件
|- .gitignore git忽略文件规则
|- babel.config.js babel配置
|- package.json 项目依赖包配置
|- vue.config.js Vue项目配置,和Flask集成配置
|- yarn.lock yarn包版本锁定文件
总结:
首页
登录
个人信息
信息修改
所有账单
付款
<template>
<div>
<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal">
<el-menu-item index="1"><router-link to="/">首页</router-link></el-menu-item>
<el-menu-item index="2"><router-link to="/login">登录</router-link></el-menu-item>
<el-menu-item index="5"><router-link to="/bills/generate">账单生成</router-link></el-menu-item>
<el-menu-item index="8"><router-link to="/clerk/unpaid_bills">收费员查账</router-link></el-menu-item>
<el-menu-item index="9"><router-link to="/clerk/charge">收费员收费</router-link></el-menu-item>
</el-menu>
</div>
<el-button @click="logout">登出</el-button>
</template>
<script>
import { logout } from '@/api'
export default {
data() {
return {
activeIndex: '1'
}
},
methods: {
logout() {
logout()
.then(() => {
this.$router.push('/')
localStorage.removeItem('access_token')
})
.catch(err => {
if (err.message === 'No access_token found.') {
console.log(err.message)
return
}
console.log(err.message)
})
}
}
}
</script>
<style scoped>
.el-menu-demo {
background-color: #545C64;
}
</style>
<!-- UserRegister.vue -->
<template>
<!-- 用户注册页面 -->
<el-form :model="data" :rules="rules" ref="form" label-width="100px">
<el-form-item label="Username" prop="Username">
<el-input v-model="data.Username"></el-input>
</el-form-item>
<el-form-item label="Password" prop="Password">
<el-input type="password" v-model="data.Password"></el-input>
</el-form-item>
<el-form-item label="PasswordConfirm" prop="PasswordConfirm">
<el-input type="password" v-model="data.PasswordConfirm"></el-input>
</el-form-item>
<el-form-item label="IDCard" prop="IDCard">
<el-input v-model="data.IDCard"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="register('form')">注册</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</template>
<script>
// 导入axios和注册接口
import { register } from '@/api'
export default {
data() {
return {
// 用户名、密码、确认密码、身份证号
data: {
Username: '',
Password: '',
PasswordConfirm: '',
IDCard: ''
},
// 表单验证规则
rules: {
// 用户名必填
Username: [
{ required: true, message: '请输入用户名', trigger: 'blur' }
],
// 密码必填、6位以上
Password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, message: '密码长度不能少于6位', trigger: 'blur' }
],
// 确认密码必填、与密码一致
PasswordConfirm: [
{ required: true, message: '请再次输入密码', trigger: 'blur' },
{ validator: this.confirmPassword, trigger: 'blur' }
],
// 身份证号必填
IDCard: [
{ required: true, message: '请输入身份证号', trigger: 'blur' }
]
}
}
},
methods: {
// 确认密码自定义校验方法
confirmPassword(rule, value, callback) {
console.log('调用confirmPassword方法,Password值为:', this.data.Password)
console.log('调用confirmPassword方法,PasswordConfirm值为:', value)
if (value !== this.data.Password) {
callback(new Error('两次输入的密码不一致!'))
console.log('两次密码输入不一致!')
} else {
callback()
console.log('两次密码输入一致!')
}
},
register(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
const params = {
Username: this.data.Username,
Password: this.data.Password,
IDCard: this.data.IDCard
}
register(params)
.then(res => {
if (res.data.errno === 0) {
this.$message.success('注册成功!')
this.$router.push('/login') // 跳转到登录页
}else{
console.log('接受到结果为:', res.data.errmsg)
this.$message.error(res.data.errmsg)
}
})
.catch(err => {
if (err.response.data.errno === 3001) {
this.$message.error(`${err.response.data.errmsg}`)
} else if (err.response.data.errno === 3002) {
this.$message.error(`${err.response.data.errmsg}`)
} else if (err.response.data.errno === 4001) {
this.$message.error(`${err.response.data.errmsg}`)
}else {
this.$message.error('注册失败!')
}
})
} else {
this.$message.error('注册信息不完整!')
return false
}
})
}
}
}
</script>
<template>
<form @submit.prevent="submitLogin">
<div>
<label for="Username">用户名</label>
<input v-model="user.Username" name="Username">
</div>
<div>
<label for="Password">密码</label>
<input v-model="user.Password" name="Password" type="password">
</div>
<button type="submit">登录</button>
</form>
</template>
<script>
import { login } from '@/api'
import jwt_decode from 'jwt-decode'
export default {
data() {
return {
user: {
Username: '',
Password: ''
}
}
},
methods: {
async login() {
console.log('login 方法被调用')
try {
if (!this.user.Username || !this.user.Password) {
throw new Error('请输入用户名和密码')
}
console.log('发起登录请求')
const res = await login(this.user)
console.log('登录请求成功,获取响应结果')
if (res.data && res.data.access_token) {
// 存储token
localStorage.setItem('access_token', res.data.access_token)
console.log(`用户 ${this.user.Username} 登录成功!access_token ${res.data.access_token} 已存储`)
const accessToken = localStorage.getItem('access_token')
const claims = jwt_decode(accessToken, 'secret')
console.log('claims:', claims)
const role = claims.privilege
if (role == 1 || role ==0) {
this.$router.push({ path: '/c' })
}
else{
this.$router.push({ path: '/profile' })
}
} else {
console.log(`用户 ${this.user.Username} 登录失败,请检查用户名 ${this.user.Username} 和密码`)
}
} catch (err) {
console.log(err.message)
}
},
submitLogin() {
console.log('submitLogin 方法被调用')
this.login()
}
}
}
</script>
<!-- src\views\UpdateProfile.vue -->
<template>
<div>
<el-form ref="updateForm" :model="user" status-icon :rules="rules" @submit.prevent="submitUpdateProfile">
<el-form-item label="真实姓名" prop="RealName">
<el-input v-model="user.RealName" />
</el-form-item>
<el-form-item label="手机号" prop="Phone">
<el-input v-model="user.Phone" />
</el-form-item>
<el-form-item label="邮箱" prop="Email">
<el-input v-model="user.Email" />
</el-form-item>
<el-form-item label="地址" prop="Address">
<el-input v-model="user.Address" />
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit">更新</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { ElForm, ElFormItem, ElInput, ElButton } from 'element-plus';
import { updateProfile } from '@/api';
export default {
components: {
ElForm,
ElFormItem,
ElInput,
ElButton,
},
data() {
return {
user: {
RealName: '',
Phone: '',
Email: '',
Address: '',
},
rules: {
RealName: [{ required: true, message: '请输入真实姓名', trigger: 'blur' }],
Phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3459]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' },
],
Email: [
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' },
],
Address: [{ required: true, message: '请输入地址', trigger: 'blur' }],
},
};
},
methods: {
submitUpdateProfile() {
this.$refs.updateForm.validate(valid => {
if (valid) {
this.updateProfile();
} else {
return false;
}
});
},
updateProfile() {
updateProfile(this.user)
.then(() => {
this.$message({
message: '资料更新成功',
type: 'success',
});
this.$router.push('/Profile');
console.log('user对象填充成功:', this.user)
})
.catch(err => {
console.log(err.message);
this.$router.push('/');
});
},
},
};
</script>
<!-- <template>
<div>
<form @submit.prevent="updateProfile">
<div>
<label for="RealName">真实姓名</label>
<input v-model="user.RealName">
</div>
<div>
<label for="Phone">手机号</label>
<input v-model="user.Phone">
</div>
<div>
<label for="Email">邮箱</label>
<input v-model="user.Email">
</div>
<div>
<label for="Address">地址</label>
<input v-model="user.Address">
</div>
<button type="submit">更新</button>
</form>
</div>
</template>
<script>
import { updateProfile } from '@/api'
export default {
data() {
return {
user: {}
}
},
methods: {
updateProfile() {
updateProfile(this.user)
.then(() => {
this.$router.push('/Profile')
})
.catch(err => {
console.log(err.message)
})
}
}
}
</script> -->
<template>
<div>
<form @submit.prevent="generateUnpaidBill">
<div>
<label for="year">Year:</label>
<input id="year" v-model="unpaidBillForm.year">
</div>
<div>
<label for="month">Month:</label>
<input id="month" v-model="unpaidBillForm.month">
</div>
<button type="submit">Generate Unpaid Bill</button>
</form>
</div>
</template>
<script>
import { generateUnpaidBill } from '@/api'
export default {
data() {
return {
unpaidBillForm: {
year: '',
month: ''
}
}
},
methods: {
generateUnpaidBill() {
// 获取 access_token
const accessToken = localStorage.getItem('access_token')
// 调用方法,传入 accessToken
generateUnpaidBill(this.unpaidBillForm, accessToken)
.then(res => {
alert(res.data.errmsg)
})
.catch(err => {
if (err === '权限不足,无法生成未付账单') {
alert(err)
} else {
alert('Generate unpaid bill failed. Please try again!')
}
})
}
}
}
</script>
<template>
<div>
<button @click="getUnpaidBills">获取未付账单</button>
<button @click="toHome">回首页</button>
<table>
<thead>
<tr>
<th>账单ID</th>
<th>用户ID</th>
<th>应收金额</th>
<th>账期</th>
<th>还款状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="bill in bills" :key="bill.BillID">
<td>{{ bill.BillID }}</td>
<td>{{ bill.UserID }}</td>
<td>{{ bill.TotalCost }}</td>
<td>{{ bill.Year }}年{{ bill.Month }}月</td>
<td>{{ bill.PaidStatus }}</td>
<td>
<button @click="toPay(bill)">支付</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { queryUnpaidBills } from '@/api'
export default {
data() {
return {
bills: []
}
},
methods: {
getUnpaidBills() {
console.log('调用获取未付账单方法')
queryUnpaidBills().then(res => {
console.log('获取未付账单成功,结果:', res)
this.bills = res.data.data
console.log('bills:', this.bills)
}).catch(err => {
console.log('获取未付账单失败,错误:', err)
})
},
toHome() {
this.$router.push('/')
},
toPay(bill) {
const dataToSave = { billID: bill.BillID, totalCost: bill.TotalCost };
localStorage.setItem("chargeData", JSON.stringify(dataToSave));
this.$router.push({ name: "pay" });
// console.log('跳转到支付路由,传入账单ID:', bill.bill_id)
// this.$router.push({
// name: 'pay',
// params: {
// billID: bill.BillID,
// }
// })
}
}
}
</script>
<template>
<div>
<h2>网上支付</h2>
<form @submit.prevent="chargeBill" novalidate>
<p>账单ID: {{ billId }}</p>
<p>应付金额: {{ totalCost }}</p>
<input
type="number"
placeholder="输入缴费金额"
v-model="paidFee"
/>
<div v-if="errorMsg" class="error">{{ errorMsg }}</div>
<button type="submit">支付</button>
</form>
</div>
</template>
<script>
import { makePayment } from '@/api'
export default {
data() {
const receivedData = JSON.parse(localStorage.getItem("chargeData"));
return {
billId: receivedData.billID,
totalCost: receivedData.totalCost,
paidFee: '',
errorMsg: '',
};
},
methods: {
chargeBill() {
if (!this.validatePaidFee()) {
return;
}
const data = {
bill_id: this.billId,
paid_fee: this.paidFee,
};
makePayment(data)
.then((res) => {
console.log('支付成功', res);
this.errorMsg = '';
})
.catch((err) => {
console.log('支付失败', err);
});
},
validatePaidFee() {
if (parseFloat(this.paidFee).toFixed(1) !== parseFloat(this.totalCost).toFixed(1)) {
this.errorMsg = '支付金额和账单金额不一致,请重新输入';
return false;
}
return true;
},
},
mounted() {
localStorage.removeItem("chargeData");
},
};
</script>
<style scoped>
.error {
color: red;
}
</style>
<template>
<div>
<h2>职员收费页面</h2>
<form @submit.prevent="chargeBill" novalidate>
<p>账单ID: {{ billId }}</p>
<p>应收金额: {{ totalCost }}</p>
<input
type="number"
placeholder="输入实收金额"
v-model="paidFee"
/>
<div v-if="errorMsg" class="error">{{ errorMsg }}</div>
<button type="submit">收费</button>
</form>
</div>
</template>
<script>
import { clerkCharge } from '@/api';
export default {
data() {
const receivedData = JSON.parse(localStorage.getItem("chargeData"));
return {
billId: receivedData.billID,
totalCost: receivedData.totalCost,
paidFee: '',
errorMsg: '',
};
},
methods: {
chargeBill() {
if (!this.validatePaidFee()) {
return;
}
const data = {
bill_id: this.billId,
paid_fee: this.paidFee,
};
clerkCharge(data)
.then((res) => {
console.log('收费成功', res);
this.errorMsg = '';
})
.catch((err) => {
console.log('收费失败', err);
});
},
validatePaidFee() {
if (parseFloat(this.paidFee).toFixed(1) !== parseFloat(this.totalCost).toFixed(1)) {
this.errorMsg = '收费金额和账单金额不一致,请重新输入';
return false;
}
return true;
},
},
mounted() {
localStorage.removeItem("chargeData");
},
};
</script>
<style scoped>
.error {
color: red;
}
</style>
<template>
<div>
<h2>职员收费页面</h2>
<el-form @submit.prevent="chargeBill" novalidate>
<p>账单ID: {{ billId }}</p>
<p>应收金额: {{ totalCost }}</p>
<el-input type="number" placeholder="输入实收金额" v-model="paidFee" />
<div v-if="errorMsg" class="error">{{ errorMsg }}</div>
<el-button type="primary" native-type="submit">收费</el-button>
</el-form>
</div>
</template>
<script>
import { clerkCharge } from "@/api";
export default {
data() {
const receivedData = JSON.parse(localStorage.getItem("chargeData"));
return {
billId: receivedData.billID,
totalCost: receivedData.totalCost,
paidFee: "",
errorMsg: "",
};
},
methods: {
async chargeBill() {
if (!this.validatePaidFee()) {
return;
}
const data = {
bill_id: this.billId,
paid_fee: this.paidFee,
};
try {
const res = await clerkCharge(data);
console.log("收费成功", res);
this.errorMsg = "";
} catch (err) {
console.log("收费失败", err);
}
},
validatePaidFee() {
if (
parseFloat(this.paidFee).toFixed(1) !==
parseFloat(this.totalCost).toFixed(1)
) {
this.errorMsg = "收费金额和账单金额不一致,请重新输入";
return false;
}
return true;
},
},
mounted() {
localStorage.removeItem("chargeData");
},
};
</script>
<style scoped>
.error {
color: red;
}
</style>
<template>
<div>
<button @click="getUnpaidBills">获取未付账单</button>
<button @click="toHome">回首页</button>
<table>
<thead>
<tr>
<th>账单ID</th>
<th>用户ID</th>
<th>应收金额</th>
<th>账期</th>
<th>还款状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="bill in bills" :key="bill.BillID">
<td>{{ bill.BillID }}</td>
<td>{{ bill.UserID }}</td>
<td>{{ bill.TotalCost }}</td>
<td>{{ bill.Year }}年{{ bill.Month }}月</td>
<td>{{ bill.PaidStatus }}</td>
<td>
<button @click="toCharge(bill)">收费</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { getClerkUnpaidBills } from '@/api';
export default {
data() {
return {
bills: [],
};
},
methods: {
getUnpaidBills() {
console.log('调用获取未付账单方法');
getClerkUnpaidBills()
.then((res) => {
console.log('获取未付账单成功,结果:', res);
this.bills = res.data.data;
console.log('bills:', this.bills);
})
.catch((err) => {
console.log('获取未付账单失败,错误:', err);
});
},
toHome() {
this.$router.push('/');
},
// toCharge(bill) {
// this.$router.push({
// name: 'charge',
// // query: { billID: bill.BillID, totalCost: bill.TotalCost },
// });
// },
toCharge(bill) {
const dataToSave = { billID: bill.BillID, totalCost: bill.TotalCost };
localStorage.setItem("chargeData", JSON.stringify(dataToSave));
this.$router.push({ name: "charge" });
},
},
};
</script>
<template>
<div>
<h1>软删除用户</h1>
<el-form ref="form" :model="formData" label-width="100px">
<el-form-item label="用户ID">
<el-input v-model="formData.user_id"></el-input>
</el-form-item>
<el-form-item>
<el-button type="danger" @click="softDeleteUser()">软删除</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { softDelete } from '@/api';
export default {
data() {
return {
formData: {
user_id: '',
},
};
},
methods: {
async softDeleteUser() {
try {
console.log('软删除方法开始调用', this.formData);
await softDelete({ user_id: this.formData.user_id });
console.log('软删除成功', this.formData);
this.$message({
message: '软删除成功!',
type: 'success',
});
// 在这里添加其他代码以更新您的 UI 或进行其他操作
} catch (err) {
console.error('软删除失败', err);
this.$message({
message:'软删除失败!',
type: 'error',
});
// 在这里添加其他代码以更新您的 UI 或进行其他操作
}
},
},
};
</script>
// vue-web\src\router\index.js
import { createRouter, createWebHistory } from 'vue-router';
import HomePage from '../views/HomePage.vue'
import ClerkPage from '../views/ClerkPage.vue'
import UserRegister from '../views/UserRegister.vue'
import UserLogin from '../views/UserLogin.vue'
import UserhardDel from '../views/UserhardDel.vue'
import UsersoftDel from '../views/UsersoftDel.vue'
import UserProfile from '../views/UserProfile.vue'
import UpdateProfile from '../views/UpdateProfile.vue'
import GenerateUnpaidBill from '../views/GenerateUnpaidBill.vue';
import QueryUnpaidBills from '../views/QueryUnpaidBills';
import MakePayment from '../views/MakePayment.vue';
import GetClerkUnpaidBills from '../views/GetClerkUnpaidBills.vue';
import ClerkCharge from '../views/ClerkCharge.vue';
// rest of your router configurations ...
const routes = [
{
path: '/',
component: HomePage
},
{
path: '/c',
component:ClerkPage
},
{
path: '/login',
component: UserLogin
},
{
path: '/users/register',
component: UserRegister
},
{
path: '/users/soft_delete',
component: UsersoftDel
}, {
path: '/users/hard_delete',
component: UserhardDel
},
{
path: '/profile',
component: UserProfile,
},
{
path: '/profile/update',
component: UpdateProfile
},
{
path: '/bills/generate',
component: GenerateUnpaidBill
},
{
path: '/bills',
component: QueryUnpaidBills
},
{
name: 'pay',
path: '/payments',
component: MakePayment
},
{
path: '/clerk/unpaid_bills',
component: GetClerkUnpaidBills
},
{
name: 'charge',
path: '/clerk/charge',
component: ClerkCharge
}
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
// vue-web\src\router\index.js
import { createRouter, createWebHistory } from 'vue-router';
import HomePage from '../views/HomePage.vue'
import ClerkPage from '../views/ClerkPage.vue'
import UserRegister from '../views/UserRegister.vue'
import UserLogin from '../views/UserLogin.vue'
import UserProfile from '../views/UserProfile.vue'
import UpdateProfile from '../views/UpdateProfile.vue'
import GenerateUnpaidBill from '../views/GenerateUnpaidBill.vue';
import QueryUnpaidBills from '../views/QueryUnpaidBills';
import MakePayment from '../views/MakePayment.vue';
import GetClerkUnpaidBills from '../views/GetClerkUnpaidBills.vue';
import ClerkCharge from '../views/ClerkCharge.vue';
// rest of your router configurations ...
const routes = [
{
path: '/',
component: HomePage
},
{
path: '/c',
component:ClerkPage
},
{
path: '/login',
component: UserLogin
},
{
path: '/register',
component: UserRegister
},
{
path: '/profile',
component: UserProfile,
},
{
path: '/profile/update',
component: UpdateProfile
},
{
path: '/bills/generate',
component: GenerateUnpaidBill
},
{
path: '/bills',
component: QueryUnpaidBills
},
{
name: 'pay',
path: '/payments',
component: MakePayment
},
{
path: '/clerk/unpaid_bills',
component: GetClerkUnpaidBills
},
{
name: 'charge',
path: '/clerk/charge',
component: ClerkCharge
}
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
// vue-web\src\api.js
import axios from 'axios'
import jwt_decode from 'jwt-decode'
const API_URL = 'http://localhost:5000'
// axios配置
axios.defaults.baseURL = API_URL
axios.defaults.headers.post['Content-Type'] = 'application/json'
axios.defaults.headers.delete['Content-Type'] = 'application/json'
axios.defaults.headers.get['Authorization'] = `Bearer ${localStorage.getItem('access_token')}`
export const login = (data) => {
return new Promise((resolve, reject) => {
axios.post('/login', data)
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
// 获取用户信息
export const getProfile = () => {
return new Promise((resolve, reject) => {
axios.get('/profile', { // 增加配置对象,设置请求头
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
})
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
// 更新用户信息
export const updateProfile = (user) => {
return new Promise((resolve, reject) => {
axios.put('/profile/update', user, {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
})
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
export const logout = () => {
return new Promise((resolve, reject) => {
const access_token = localStorage.getItem('access_token')
if (!access_token) {
reject(new Error('No access_token found.'))
}
axios.post('/logout', {}, {
headers: {
Authorization: `Bearer ${access_token}`
}
})
.then(res => {
resolve(res)
localStorage.removeItem('access_token')
})
.catch(err => {
reject(err)
})
})
}
export const register = (data) => {
// 使用用户名、密码和身份证号进行注册
console.log('调用注册接口,参数:', data)
return new Promise((resolve, reject) => {
axios.post('/users/register', data)
.then(res => {
// 注册成功,返回结果
console.log('注册成功:', res.data)
resolve(res)
})
.catch(err => {
// 注册失败,返回错误
console.log('注册失败:', err.response.data)
reject(err)
})
})
}
export const generateUnpaidBill = (data) => {
// 获取本地存储的用户角色
// 解码 access_token,获取 claims
const accessToken = localStorage.getItem('access_token')
const claims = jwt_decode(accessToken, 'secret')
console.log('claims:', claims)
const role = claims.privilege
console.log('调用生成未付账单接口, 参数:', data,role)
// 方法主体结构
return new Promise((resolve, reject) => {
// 权限判断
if (role !== 0) {
return reject('权限不足,无法生成未付账单')
}
axios.post('/bills/generate', data, {
headers: {
Authorization: `Bearer ${accessToken}`
}
})
.then(res => {
console.log('生成未付账单成功, 结果:', res.data)
resolve(res)
}).catch(err => {
console.log('生成未付账单失败, 错误:', err.response.data)
reject(err)
})
})
}
export const queryUnpaidBills = () => {
return new Promise((resolve, reject) => {
axios.get('/bills', {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
}).then(res => {
console.log('查询未付账单成功, 结果:', res.data);
resolve(res)
}).catch(err => {
console.log('查询未付账单失败, 错误:', err);
reject(err)
});
})
}
export const makePayment = (data) => {
console.log('调用付款接口, 参数:', data);
return new Promise((resolve, reject) => {
axios.post('/payments', data, {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
}).then(res => {
console.log('付款成功, 结果:', res.data);
resolve(res)
}).catch(err => {
console.log('付款失败, 错误:', err);
reject(err)
});
})
}
export const getClerkUnpaidBills = () => {
// 获取本地存储的用户角色
const accessToken = localStorage.getItem('access_token')
const claims = jwt_decode(accessToken, 'secret')
console.log('claims:', claims)
const role = claims.privilege
console.log('调用获取职员未付账单接口', {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
});
return new Promise((resolve, reject) => {
// 权限判断
if (role !== 1) {
return reject('权限不足,无法生成未付账单')
}
axios.get('/clerk/unpaid_bills').then(res => {
console.log('获取职员未付账单成功,结果:', res);
resolve(res)
}).catch(err => {
console.log('获取职员未付账单失败, 错误:', err.data);
reject(err)
});
})
}
export const clerkCharge = (data) => {
// 获取本地存储的用户角色
const accessToken = localStorage.getItem('access_token')
const claims = jwt_decode(accessToken, 'secret')
console.log('claims:', claims)
const role = claims.privilege
console.log('调用职员收费接口, 参数:', data, {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
});
return new Promise((resolve, reject) => {
if (role !== 1) {
return reject('权限不足,无法生成未付账单')
}
axios.post('/clerk/charge', data).then(res => {
console.log('职员收费成功, 结果:', res.data);
resolve(res)
}).catch(err => {
console.log('职员收费失败, 错误:', err.data);
reject(err)
});
})
}
export const hardDelete = (data) => {
// 获取本地存储的用户角色
const accessToken = localStorage.getItem('access_token')
const claims = jwt_decode(accessToken, 'secret')
console.log('claims:', claims)
// const role = claims.privilege
console.log('调用删除接口, 参数:', data, {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
});
return new Promise((resolve, reject) => {
// if (role !== 1) {
// return reject('权限不足,无法删除用户')
// }
axios.delete('/users/hard_delete', data).then(res => {
console.log('删除成功, 结果:', res.data);
resolve(res)
}).catch(err => {
console.log('删除失败, 错误:', err.data);
reject(err)
});
})
}
export const softDelete = (data) => {
// 获取本地存储的用户角色
const accessToken = localStorage.getItem('access_token')
const claims = jwt_decode(accessToken, 'secret')
console.log('claims:', claims)
// const role = claims.privilege
console.log('调用删除接口, 参数:', data, {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
});
return new Promise((resolve, reject) => {
// if (role !== 1) {
// return reject('权限不足,无法删除用户')
// }
axios.post('/users/soft_delete', data).then(res => {
console.log('删除成功, 结果:', res.data);
resolve(res)
}).catch(err => {
console.log('删除失败, 错误:', err.data);
reject(err)
});
})
}
// export const register = (data) => axios.post(`${API_URL}/users/register`, data)
export default axios
通过这个课程设计,我对数据库系统设计有了更深的理解,也掌握了使用流行技术构建项目的方法。这是一次非常棒的学习经历,让我对数据库系统的概念有了全新的认识。