QT+SQL Server 车票实名销售系统

   大二课程彻底结束,大学生活度过了一半左右。在大二下学习了数据库sql server,花了大概10天左右做了相关课程设计,写篇文章记录一下生活。代码会存在一些问题,运行是不会报错的。因为本人纯纯是新人小白,大佬请略过,接受指正。废话不多说了,直接上代码。

注:自行配置ODBC

一、功能介绍:

  此系统为车票实名系统,主要功能就是对车票进行实名的销售。分为用户部分和管理员部分。用户部分首先有用户实名注册部分。登录部分采用用户名称登录。主要功能为 车票查询、车票购买、退票、个人主页详情查看订单等功能。车票查询就是可以查询从起点到终点是否有车次,并显示相关的信息(例如到站信息等等)。此系统只能简单自行买票和退票,能够查询到所有有票的信息。管理员部分就是对一些后台信息进行基本的操作。

用户:

管理员:

功能介绍(用户)

        用户首先可以进行登录,如果不在系统中,可以进行注册功能。其中姓名、邮箱、密码和身份证号为必须填写。登录成功后首先功能为简单查询,简单查询分为正晚点和检票口查询。正晚点查询需要输入车站、是否为出发站、是否为到达站来进行查询、以及车次;同理检票口查询需要输入日期、车次、乘车站进行查询。之后为车票购买功能。

    通过输入想何时购票,分为输入乘车日期、到达站、车次、座位席位、上车站。然后会出现目前已经有的票。通过双击进行订票,如果成功订票则会出现自动生成的订单号。之后在个人主页详情中可以看到自己成功订票的订单具体消息。如果不想要这张票。则通过双击这张票,并且会弹出退票的消息窗口。之后退票,订单消失,这张票则会出现在车票购买这一栏。

  功能介绍(管理员)

         通过主窗体输入管理员的姓名和登录密码。登录后可以看到车次管理、站点管理、座位管理和车票管理还有订单查看,管理员没有权利删除订单,订单是自动创建和自动删除的。管理员可以管理这些表的信息。最后还有一个销售统计。销售统计通过输入对应的日期,然后查看当日的车票售卖情况。这是一个综合的统筹。

二、数据库设计:

(数据请自行设计)

数据表的创立:

sql:

一共有10张表。这里说明一下,TrainRoute有一个字段是DirectionArrangement,这里本来想做一个中转站,但是时间不够了,所以字段都为1,如果想扩展可以2,3.......

--1.表CustomerInfo:(顾客信息)
create table CustomerInfo(
IDCardNumber char(18) not null primary key, --身份证的长度为18位作为主键
Name varchar(50) not null,--姓名最长为50个字符
Occupation varchar(100),--职业,最长为100个字符
Gender char(1) check(Gender IN('M','F')), --男/女选择
Age INT, --年龄为int类型
Password varchar(50) not null,
Email varchar(100) UNIQUE,--unique约束是确保邮箱唯一
);
--2.表StationInfo:(站点信息)
create table StationInfo(
  StationSerialNumber int not null primary key,--站点序号作为主键
  StationInfoDetails varchar(255) not null --站点信息长度,最长255个字符
);
--3.表TrainSchedule:(车次信息)
create table TrainSchedule(
TrainNumber varchar(10) not null,
TrainType varchar(10) not null check(TrainType in('高铁','动车')),
StartPoint varchar(50) not null,
EndPoint varchar(50) not null,
DepartureTime datetime not null,
ArrivalTime datetime not null,
RunningTime as datediff(minute,DepartureTime,ArrivalTime)persisted,
primary key (TrainNumber,DepartureTime),
check(RunningTime>=0 and ArrivalTime>DepartureTime)
)
--4.表SeatInfo的建立:(座位信息)
Create Table SeatInfo(
CarriageNumber varchar(10) not null,
ClassLevel varchar(10) not null,
SeatNumber varchar(10) not null,
TrainNumber varchar(10) not null,
primary key(CarriageNumber,ClassLevel,SeatNumber,TrainNumber),
money int not null 
)
ALTER TABLE TrainSchedule
ADD CONSTRAINT UK_TrainNumber UNIQUE (TrainNumber);//约束条件
--5.表TrainRoute的建立:(车次路线表)
create table TrainRoute
(
TrainNumber varchar(10) not null,
DepartureTime datetime not null,
ArrivalTime datetime not null,
RunningTime as datediff(minute,DepartureTime,ArrivalTime)persisted,
DirectionArrangement int not null,
Mileage float not null,
PRIMARY KEY (TrainNumber, DepartureTime), -- 复合主键
    FOREIGN KEY (TrainNumber, DepartureTime) REFERENCES TrainSchedule(TrainNumber, DepartureTime), -- 引用TrainSchedule的复合主键
)
--6.表TicketInfo的建立:(车票信息表)
CREATE TABLE TicketInfo(
ticketID int primary key not null,  --注意新加字段  
TrainNumber varchar(10) not null,
DepartureTime datetime not null,
CarriageNumber varchar(10) not null,
ClassLevel varchar(10) not null,
SeatNumber varchar(10) not null,
foreign key(TrainNumber,DepartureTime) references TrainSchedule(TrainNumber,DepartureTime) on delete cascade on update cascade,
foreign key(CarriageNumber,ClassLever,SeatNumber)references SeatInfo(CarriageNumber,ClassLever,SeatNumber)on delete cascade on update cascade
)
--on delete cascade on update cascade,意味着父表中的记录删除或者更新,子表中相应的外键也会更新。
--7. TicketOrder (订单表):
create table TicketOrder( --在这个表上建立一个触发器,刚买完票则会自动生成一个订单,这个表就不用建立外键什么约束用的
    OrderID INT IDENTITY(1,1) PRIMARY KEY,--这里是订单号,生成的自动递增
	TrainNumber varchar(10) not null,
	DepartureTime datetime not null,
	StartPoint varchar(50) not null,
	EndPoint varchar(50) not null,
	CarriageNumber varchar(10) not null,
ClassLevel varchar(10) not null,
	SeatNumber varchar(10) not null,
	money int not null,
 PurchaseDate DATE DEFAULT  getdate(),
	IsNormalUse CHAR(1) CHECK (IsNormalUse IN ('F', 'T')) NOT NULL  -- 是否正常使
Name char(50) not null用,约束为'F'或'T'
)
--8.SeatInfo_Delete是用来存储已经订票的信息:
Create Table SeatInfo_Delete(
CarriageNumber varchar(10) not null,
ClassLeverl varchar(10) not null,
SeatNumber varchar(10) not null,
TrainNumber varchar(10) not null,
primary key(CarriageNumber,ClassLeverl,SeatNumber,TrainNumber),
money int not null ,
Name varchar(50) not null
)
--9. TicketInfo_Delete用来存储已经订票备份信息:
CREATE TABLE TicketInfo_Delete(
ticketID int primary key not null,  --注意新加字段  
TrainNumber varchar(10) not null,
DepartureTime datetime not null,
CarriageNumber varchar(10) not null,
ClassLever varchar(10) not null,
SeatNumber varchar(10) not null,
)
  -- 10Manger表(管理员表):
CREATE TABLE Manager
(
  Name varchar(50) primary key not null,
  Password varchar(50) not null
)

概念结构设计:

E-R图:

注:这里E-R图还有3张图,它们的作用是存储删除信息的还有存储manager的姓名密码,为突出关系,只用以上图展示。

用户角度:(主要)

实体:车次信息 (TrainSchedule ) 属性:车次、类型(高铁、动车)、起点、终点、发车时间、到达时间、运行时间。

实体:车次路线表(TrainRoute)属性:车次、到达时间、发车时间、停留时间、方向排序、里程 。

实体:座位信息(SeatInfo)  属性:车次、车厢号、等级、座位号、价钱。

实体:站点信息 (StationInfo)属性:站点序号、站点信息

实体:车票信息 (TicketInfo) 属性:车票编号,车次、发车日期、车厢号、等级、空余座位号。

实体:顾客信息(CustomerInfo)属性:身份证号、姓名、职业、性别、年龄、密码、邮箱号。

实体:车票购买信息(TicketOrder)属性:车次、发车日期、起点站、终点站、车厢号、座位号、姓名、票价、购买日期,是否正常使用(退票记录保留时判断),订单号价格。

逻辑结构设计:

1.关系模式:

车次路线(车次,到达时间,发车时间,停留时间,方向排序,里程);

座位信息(车次,车厢号,等级,座位号,价钱);

车次信息(车次发车时间,类型,起点,终点,到达时间,运行时间,站点序号);

站点信息(站点序号,站点信息);

车票购买信息(订单号,车次,发车日期,起点站,终点站,车厢号,座位号,姓名,票价,购买点,购买日期,是否正常使用,身份证号,);

车票信息(车票编号,车次,发车日期,车厢号,等级,空余座位号);

顾客信息(身份证号,姓名,职业,性别,年龄,密码,邮箱号,车票编号,车次);

查询(顾客信息,车次路线);

2.空值信息:

上文的字段基本上都不能为空,除了顾客信息表中的职业,性别,年龄。

3.属性信息:

车次(varchar(10),类型(varchar10)),起始点(varchar50)),终点(varchar(50),发车时间(datetime),到达时间(datetime),运行时间,站点序号(int),方向排列(int),公里数(float),订单号(int),车厢号(varchar10)),等级(varchar10),身份证号(char18)),购买日期(date),是否正常使用(char1)),票的序号(int),姓名(varchar50)),职业(varchar100)),性别(char1)),年龄(int),passwordvarchar50)),Emailvarchar100)),座位号(varchar10)),票钱(int),站点信息(varchar(255)

物理结构设计:

 索引建立:

1.再车票查询的时候,根据所输入的信息定义索引,其中定义发车日期是必须要最左索引定义。

 2.车次路线图中建立索引。其中索引中字段为车次,站点信息,发车时间,方向排序,方向排序是按照升序排序的(升序排序这里未实现,因为此系统未考虑中间段)

硬件优化:

(1)增加内存:增大数据库服务器的内存容量,可以提高缓冲池的大小,使更多的数据和索引驻留在内存中,减少磁盘I/O操作。

(2)使用固态硬盘:相比传统的机械硬盘,SSD提供了更高的读写速度,可以显著减少I/O等待时间。

(3)CPU升级:更强的处理器能更快地处理复杂的查询和事务处理,尤其在高并发场景下更为明显。

(4)网络优化:确保数据库服务器的网络连接高速稳定,减少网络延迟对数据库性能的影响。

 数据库配置优化:

(1)调整缓存设置:合理配置数据库缓存大小,如MySQL的InnoDB Buffer Pool,确保常用数据被缓存。

 (2)日志配置:调整事务日志的大小和刷新频率,平衡数据安全性与性能需求。

 (3)并发控制:调整并发连接数、锁机制等,避免过多的锁竞争导致的阻塞问题。

 (4)自动维护任务:安排在低峰时段执行如索引重建、统计信息更新等操作,减少对在线服务的影响。

数据模型优化:

 (1)范式化与反范式化:根据应用场景权衡,适度反范式化(如冗余数据)以减少JOIN操作,提高查询效率,但需注意数据一致性。

 (2)数据归档:定期迁移历史数据到归档表或低成本存储,减少在线表的大小,提高查询速度。

应用程序优化:

 (1)减少数据库调用:通过批量操作、缓存策略减少对数据库的频繁请求。

监控与调优:

 (1)性能监控:持续监控数据库的各项性能指标,如CPU使用率、I/O等待、慢查询等,及时发现并解决问题。

 (2)定期评估与调优:根据监控数据和业务变化,定期评估数据库性能,适时进行调整和优化。

数据库触发器、存储过程等设计与测试:

触发器:

1.当卖出车票时,自动删除空余座位信息和车票空余记录,并且在相应的delete表中更新记录,和自动生成订单表

        2.执行退票的操作时,自动删除delete表中的记录和将剩余座位信息重载到原来的表中(这里可以用事务),并且相应删除订单。(这里是反向触发器)

存储过程:

  1. 按车次、类型及座位等级统计座位总量。
  2. 执行购票操作。
  3. 注册信息时采用存储过程进行注册。
  4. 在简单功能查询的时候用到了存储过程。(3个)
  5. 在最后进行统筹规划的时候利用输入日期写了一个存储过程自动进行统筹。(管理员)

Check约束:

1.实施CHECK约束,如到站时间必须早于发车时间等。

           2. 实施CHECK约束,约束车次类型为:高铁、动车。

           3. 实施CHECK约束,性别gender只允许为‘M’或者‘F’。

           4. 实施CHECK约束,TrainSchedule表中的runningTime列是必大于0的字段。

5. 实施CHECK约束,IsNormalUse字段只能为T 或者F

索引:   

1.在简单查询的时候,根据所输入的信息定义索引,其中定义车次是必须要最左索引定义.(查询这里写两个索引。)

          2.车次路线图中建立索引。

其他要求:

1.给每个表实施主键及外键约束。

          2.设定缺省约束,如购买日期时间为系统当前时间。

          3.设置非空约束,如系统基本信息均为非空。

          4. CustomerInfo中的email是唯一的。(union去重功能)

测试:

1)在简单查询时用到视图(正晚点)(视图+存储过程):

create view TrainSchedule_View as

select TrainNumber,StartPoint,EndPoint,DepartureTime,ArrivalTime

from [TrainSchedule];

GO

create procedure GetTrainSchedules

 @TrainNumber varchar(10),@StartPoint varchar(10)

 as

select TrainNumber,StartPoint,EndPoint,DepartureTime,ArrivalTime

from TrainSchedule_View

where TrainNumber=@TrainNumber and StartPoint=@StartPoint

EXEC GetTrainSchedules 'T123', '北京';

数据库中测试结果粘贴:

1)在简单查询时用到视图(正晚点)(视图+存储过程):

(4)存储过程的定义实现

SQL语句:

  1. 注册时用的存储过程:

create procedure InsertCustomer

@IDCardNumber char(18),

@Name varchar(50),

@Occupation varchar(50),

@Gender char(1),

@Age int,

@Password varchar(50),

@Email varchar(100)

as

begin

   insert into CustomerInfo(IDCardNumber,Name,Occupation,Gender,Age,Password,Email)

   Values(@IDCardNumber,@Name,@Occupation,@Gender,@Age,@Password,@Email);

end;

   2)在简单查询时用到存储过程(正晚点)(视图+存储过程):

    create view TrainSchedule_View as

select TrainNumber,StartPoint,EndPoint,DepartureTime,ArrivalTime

from [TrainSchedule];

GO

create procedure GetTrainSchedules

 @TrainNumber varchar(10),@StartPoint varchar(10)

 as

select TrainNumber,StartPoint,EndPoint,DepartureTime,ArrivalTime

from TrainSchedule_View

where TrainNumber=@TrainNumber and StartPoint=@StartPoint

EXEC GetTrainSchedules 'T123', '北京';

3)晚点查询存储过程:

create procedure GetTrainSchedules_1

 @TrainNumber varchar(10),@EndPoint varchar(10)

 as

select TrainNumber,StartPoint,EndPoint,DepartureTime,ArrivalTime

from TrainSchedule_View

where TrainNumber=@TrainNumber and EndPoint=@EndPoint

   4)检票口的查询:

    create procedure GetTrainSchedules_5

@TrainNumber varchar(10),@StartPoint varchar(50),@DepartureTime datetime

as

select TrainNumber,StartPoint

from [TrainSchedule_View] LEFT JOIN StationInfo si ON StationInfoDetails LIKE '%' + @StartPoint + '%'

where  TrainNumber=@TrainNumber  and CONVERT(date, DepartureTime) = @DepartureTime;

5)购票时候先查询是否有座位:

CREATE PROCEDURE getTrainInformation_5

    @departure_date DATE,

    @train_number VARCHAR(10),

    @boarding_station VARCHAR(50),

    @out_station VARCHAR(50),

    @seat_class VARCHAR(10)

AS

BEGIN

    SELECT

        a.TrainNumber,

        c.TrainType,

        c.StartPoint,

        c.EndPoint,

        a.DepartureTime,

        a.ArrivalTime,

        a.Mileage,

        a.RunningTime,

        b.ClassLevel AS ClassLevel,

              b.CarriageNumber,

              b.SeatNumber

    FROM

     TrainRoute AS a

    INNER JOIN

 TrainSchedule AS c ON a.TrainNumber = c.TrainNumber AND a.DepartureTime = c.DepartureTime

    INNER JOIN

        SeatInfo AS b ON b.TrainNumber = a.TrainNumber

    WHERE

        CAST(a.DepartureTime AS DATE) = @departure_date

       a.TrainNumber = @train_number

        AND c.StartPoint = @boarding_station

        AND c.EndPoint = @out_station

        AND b.ClassLevel = @seat_class  

    ORDER BY

        a.DepartureTime, b.CarriageNumber, b.SeatNumber;

END

GO

6)报表的时候用到存储过程(通过日期进行查询):

-- 创建存储过程

CREATE PROCEDURE totalmessage

    @Date DATE

AS

BEGIN

    -- 明细信息查询

    SELECT

        '明细信息' AS '类型',

        OrderID AS '订单号',

        TrainNumber AS '车次号',

        DepartureTime AS '出发时间',

        StartPoint AS '起始地点',

        EndPoint AS '终点',

        CarriageNumber AS '车厢号',

        ClassLevel AS '座位级别',

        SeatNumber AS '座位号',

        money AS '价格',

        PurchaseDate AS '购买时间',

        money AS '总销售金额',

        1 AS '总销售车票数'

    FROM

        TicketOrder

    WHERE

        PurchaseDate = @Date

   

    UNION ALL

    -- 汇总信息查询

    SELECT

        '汇总信息' AS '类型',

        count(*) AS '订单号',

        NULL AS '车次号',

        NULL AS '出发时间',

        NULL AS '起始地点',

        NULL AS '终点',

        NULL AS '车厢号',

        NULL AS '座位级别',

        NULL AS '座位号',

        NULL AS '价格',

        NULL AS '购买时间',

        SUM(money) AS '总销售金额',

        COUNT(*) AS '总销售车票数'

    FROM

        TicketOrder

    WHERE

        PurchaseDate = @Date

END;

GO

(5)触发器的定义实现

SQL语句:

订单生成测试

CREATE TRIGGER trg_HandleSeatInfoDelete

ON SeatInfo_Delete

AFTER INSERT

AS

BEGIN

    -- 从 SeatInfo 中删除相关数据

    DELETE s

    FROM SeatInfo s

    INNER JOIN inserted i ON s.CarriageNumber = i.CarriageNumber

                          AND s.ClassLevel = i.ClassLevel

                          AND s.SeatNumber = i.SeatNumber

                          AND s.TrainNumber = i.TrainNumber;

    -- 从 TicketInfo 中删除相关数据,并将它们复制到 TicketInfo_Delete

    INSERT INTO TicketInfo_Delete (ticketID, TrainNumber, DepartureTime, CarriageNumber, ClassLevel, SeatNumber)

    SELECT ti.ticketID, ti.TrainNumber, ti.DepartureTime, ti.CarriageNumber, ti.ClassLevel, ti.SeatNumber

    FROM TicketInfo ti

    INNER JOIN inserted i ON ti.TrainNumber = i.TrainNumber

                          AND ti.CarriageNumber = i.CarriageNumber

                          AND ti.ClassLevel = i.ClassLevel

                          AND ti.SeatNumber = i.SeatNumber;

    DELETE ti

    FROM TicketInfo ti

    INNER JOIN inserted i ON ti.TrainNumber = i.TrainNumber

                          AND ti.CarriageNumber = i.CarriageNumber

                          AND ti.ClassLevel = i.ClassLevel

                          AND ti.SeatNumber = i.SeatNumber;

    -- 向 TicketOrder 表中插入数据

    INSERT INTO TicketOrder (TrainNumber, DepartureTime, StartPoint, EndPoint, CarriageNumber, ClassLevel, SeatNumber, money,  IsNormalUse,Name)

    SELECT

        i.TrainNumber,

        ts.DepartureTime,

        ts.StartPoint,

        ts.EndPoint,

        i.CarriageNumber,

        i.ClassLevel,

        i.SeatNumber,

        CASE

            WHEN ci.Occupation IN ('学生', '军人') THEN i.money * 0.7

            ELSE i.money

        END, -- 直接使用 CASE 结果

       

        'T' ,-- 默认订单为正常使用状态

        i.Name

    FROM inserted i

    INNER JOIN TrainSchedule ts ON i.TrainNumber = ts.TrainNumber

                                AND i.TrainNumber = ts.TrainNumber

    INNER JOIN CustomerInfo ci

    ON ci.Name = i.Name; -- 假设 i.Name 是身份证号

END;END;数据库中测试结果粘贴:

(2)反向触发器测试:

USE [20221529_bighousework]

GO

/****** Object:  Trigger [dbo].[trg_HandleSeatInfoDelete_1]    Script Date: 2024/7/1 15:55:43 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

ALTER TRIGGER [dbo].[trg_HandleSeatInfoDelete_1]

ON [dbo].[SeatInfo]

AFTER INSERT

AS

BEGIN

    -- 从 SeatInfo 中删除相关数据

    DELETE s

    FROM SeatInfo_Delete s

    INNER JOIN inserted i ON s.CarriageNumber = i.CarriageNumber

                          AND s.ClassLevel = i.ClassLevel

                          AND s.SeatNumber = i.SeatNumber

                          AND s.TrainNumber = i.TrainNumber;

    -- 从 TicketInfo 中删除相关数据,并将它们复制到 TicketInfo_Delete

    INSERT INTO TicketInfo (ticketID, TrainNumber, DepartureTime, CarriageNumber, ClassLevel, SeatNumber)

    SELECT ti.ticketID, ti.TrainNumber, ti.DepartureTime, ti.CarriageNumber, ti.ClassLevel, ti.SeatNumber

    FROM TicketInfo_Delete ti

    INNER JOIN inserted i ON ti.TrainNumber = i.TrainNumber

                          AND ti.CarriageNumber = i.CarriageNumber

                          AND ti.ClassLevel = i.ClassLevel

                          AND ti.SeatNumber = i.SeatNumber;

    DELETE ti

    FROM TicketInfo_Delete ti

    INNER JOIN inserted i ON ti.TrainNumber = i.TrainNumber

                          AND ti.CarriageNumber = i.CarriageNumber

                          AND ti.ClassLevel = i.ClassLevel

                          AND ti.SeatNumber = i.SeatNumber;

    -- 向 TicketOrder 表中插入数据

DELETE toDel

    FROM TicketOrder toDel

    INNER JOIN inserted i ON toDel.TrainNumber = i.TrainNumber

                          AND toDel.CarriageNumber = i.CarriageNumber

                          AND toDel.ClassLevel = i.ClassLevel

                          AND toDel.SeatNumber = i.SeatNumber;

END

                           图十三、反向触发器测试

(6)索引的创建和实现:

SQL语句:

1)[TrainRoute]表的索引创建。(此为非聚集索引)

create index index_TrainRoute on [TrainRoute](TrainNumber,DepartureTime,ArrivalTime,Mileage,RunningTime);

2)在[TrainSchedule]表中建立索引:

create index index_TrainSchedule on [TrainSchedule](TrainType,StartPoint,EndPoint);

三、QT设计:

  1. 首先介绍一下具体代码的分层:

  1. Login.cpp为用户的登录界面代码相关:

  1. Newid.cpp为用户注册相关代码界面展示

  1. Manager.cpp为管理员登录相关代码展示;
  2. Central.cpp为用户主界面功能代码:

  1. Managercentra.cppl为管理员用户的主界面的功能代码;
  2. Communication.cpp为界面代码与数据库连接类;
  3. Communication1.cpp为管理员界面代码与数据库连接;
  4. Trade.cpp为订单生成界面代码;
  5. Database.cpp为QT与ODBC连接代码;
  6. Main类为主函数的入口显示;
  7. 界面展示(代码分层部分展示的不再展示)

这里双击所选列进行购买:

退票功能为双击个人订单的那一行:

管理员;

太多了不放了

四、加密

  可以对密码和身份证用加密算法,我用的证书未完全实现,只在数据库里体现,程序中未体现。(本质上没用hh)

说明:

  简单学了一点qss美化了一点,程序有不足,可以自行添加。本人接受指正,目的记录大学两年学习生活。

代码连接:

别忘了odbc密码修改和图片路径修改(有可能还在审核)

【免费】QT+SQLServer车票实名销售系统资源-CSDN文库

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值