iOS开发实战-时光记账Demo 网络版

写在前面
弄了下个人站...防止内容再次被锁定...所有东西都在这里面
welcome~
个人博客

之前写了一个本地数据库版本 戳这里
现在这个就是增加了后台 登录注册页面以及web的上传记录展示页面
含有少量php有兴趣可以看下
另外demo中包括数据库操作、json、网络请求等都没有用到第三方库,所以网络方面的逻辑可能有所欠缺,大神请轻拍。

效果

效果.gif

分析

很简单的分析把大致需要编写的模块列出

服务器交互.png

客户端部分

分析

  • 与本地版的demo相比主要是多了服务器请求操作

新增数据库内容:

  • Users表
    与Tally表关系:一对多


    user表

    相反Tally与Users的关系就是:一对多


    tally表
  • flag字段 决定是否上传

  • 需要发送请求的位置

  • 登录
  • 注册
  • 登录成功后第一次加载
  • 新增账单
  • 修改账单
  • 删除账单

代码

登录

登录时向服务器发送用户名和密码,当然只有两个结果:未注册 和 密码错误

#import "LoginViewController.h"

@interface LoginViewController ()<ServerOperationsDelegate>
@property (weak, nonatomic) IBOutlet UITextField *userNameField;
@property (weak, nonatomic) IBOutlet UITextField *userPswField;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"登录";
    [[CoreDataOperations sharedInstance] loadTallyTypeToSqlite];
    // Do any additional setup after loading the view.
}

- (void)viewWillAppear:(BOOL)animated{
    self.userNameField.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"userName"];
    self.userPswField.text = nil;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
//去注册
- (IBAction)clickRegister:(id)sender {
    [self.userPswField resignFirstResponder];
    [self.userPswField resignFirstResponder];
}

//输入检查 6-20为正常字符
- (BOOL)inputCheck:(NSString*)passWord{
    NSString *passWordRegex = @"^[a-zA-Z0-9]{6,20}+$";
    NSPredicate *passWordPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",passWordRegex];
    return [passWordPredicate evaluateWithObject:passWord];
    
}

//去登录
- (IBAction)clickLogin:(id)sender {
    
    //输入检查
    BOOL userNameCheck = [self inputCheck:self.userNameField.text];
    BOOL userPswCheck = [self inputCheck:self.userPswField.text];
    if (!userNameCheck | !userPswCheck) {
        [self showAlertInfoWithTag:999 andMessage:@"用户名或密码出错\n请输入6-20位合法字符"];
        return;
    }
    //键盘收起
    [self.userPswField resignFirstResponder];
    [self.userNameField resignFirstResponder];
    
    ServerOperations *op = [ServerOperations sharedInstance];
    op.delegate = self;
    [op loginWithUser:self.userNameField.text andPsw:self.userPswField.text];
}

//登录结果
- (void)didLoginBackWithTag:(int)tag{
    [self loginAlertWithReslut:tag];
}

//验证登录
- (void)loginAlertWithReslut:(int)result{
    switch (result) {
        case 0:
            //连接远程数据库失败
            [self showAlertInfoWithTag:result andMessage:@"连接远程数据库失败"];
            break;
        case 1:
            //验证成功
            [self performSegueWithIdentifier:@"toHome" sender:nil];
            break;
        case 2:
            //密码错误
            [self showAlertInfoWithTag:result andMessage:@"密码错误"];
            break;
        case 3:
            //用户不存在
            [self showAlertInfoWithTag:result andMessage:@"用户名不存在\n请注册"];
            break;
        default:
            break;
    }
}

//弹出提示框
- (void)showAlertInfoWithTag:(int)tag andMessage:(NSString*)message {
    UIAlertController *alertVC =[UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    [alertVC addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
    if (tag == 3) {
        [alertVC addAction:[UIAlertAction actionWithTitle:@"注册" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self performSegueWithIdentifier:@"toRegister" sender:nil];
        }]];
    }
    [self presentViewController:alertVC animated:YES completion:nil];
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    NSLog(@"准备push");
    //本地保存用户名
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isLoaded"];
    [[NSUserDefaults standardUserDefaults] setObject:self.userNameField.text forKey:@"userName"];
    
}
@end

注册

注册也很简单,发送注册信息给服务器,服务器判断下用户名是否存在就行。

#import "RegisterViewController.h"

@interface RegisterViewController ()<ServerOperationsDelegate>
@property (weak, nonatomic) IBOutlet UITextField *userNameField;
@property (weak, nonatomic) IBOutlet UITextField *userPswField;

@end

@implementation RegisterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"注册";
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//输入检查 6-20为正常字符
- (BOOL)inputCheck:(NSString*)passWord{
    NSString *passWordRegex = @"^[a-zA-Z0-9]{6,20}+$";
    NSPredicate *passWordPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",passWordRegex];
    return [passWordPredicate evaluateWithObject:passWord];
    
}

- (void)didRegisterBackWithTag:(int)tag{
    [self loginAlertWithReslut:tag];
}

//提交注册
- (IBAction)clickRegister:(id)sender {
    
    //输入检查
    BOOL userNameCheck = [self inputCheck:self.userNameField.text];
    BOOL userPswCheck = [self inputCheck:self.userPswField.text];
    if (!userNameCheck | !userPswCheck) {
        [self showAlertInfoWithTag:0 andMessage:@"用户名或密码出错\n请输入6-20位合法字符"];
        return;
    }
    
    //取消键盘响应
    [self.userNameField resignFirstResponder];
    [self.userPswField resignFirstResponder];

    ServerOperations *ops = [ServerOperations sharedInstance];
    ops.delegate = self;
    [ops registerWithUser:self.userNameField.text andPsw:self.userPswField.text];
}

//登录提示
- (void)loginAlertWithReslut:(int)result{
    switch (result) {
        case 0:
            //连接远程数据库失败
            [self showAlertInfoWithTag:0 andMessage:@"连接远程数据库失败"];
            break;
        case 1:
            //注册成功
            [self showAlertInfoWithTag:1 andMessage:@"注册成功"];
            break;
        case 2:
            //注册失败 用户已经存在
            [self showAlertInfoWithTag:2 andMessage:@"注册失败\n用户已经存在"];
            break;
        default:
            break;
    }
}

//弹出提示框
- (void)showAlertInfoWithTag:(int)tag andMessage:(NSString*)message {
    UIAlertController *alertVC =[UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    if (tag == 1) {
        [alertVC addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [[NSUserDefaults standardUserDefaults] setObject:self.userNameField.text forKey:@"userName"];
            [self.navigationController popViewControllerAnimated:YES];
        }]];

    }else{
        [alertVC addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];

    }
    [self presentViewController:alertVC animated:YES completion:nil];
}

@end

向服务器发送的请求操作

整个操作写成一个单例

#import <Foundation/Foundation.h>
#import "CoreDataOperations.h"

//服务器地址
//static NSString* const kServerUrl = @"http://localhost/timetally/";
static NSString* const kServerUrl = @"http://timetallydemo.duapp.com/";

@protocol ServerOperationsDelegate <NSObject>

@optional

//登录结果回调
- (void)didLoginBackWithTag:(int)tag;
//注册结果回调
- (void)didRegisterBackWithTag:(int)tag;
//成功上传
- (void)didUploadTallySuccessed;
//上传失败
- (void)didUploadTallyFaild;

@end

@interface ServerOperations : NSObject

@property(nonatomic,strong)id<ServerOperationsDelegate> delegate;

+ (instancetype)sharedInstance;
//发送服务器请求加载数据
- (void)loadDataFormServer;
//上传账单至服务器
- (void)uploadTallyToServer;
//服务器删除指定账单
- (void)deleteTallyInServerWithIdentity:(NSString*)identity;

//登录到服务器
- (void)loginWithUser:(NSString*)username andPsw:(NSString*)psw;
//注册到服务器
- (void)registerWithUser:(NSString*)username andPsw:(NSString*)psw;
@end
#import "ServerOperations.h"

@implementation ServerOperations
static ServerOperations *instance = nil;

+ (instancetype)sharedInstance
{
    return [[ServerOperations alloc] init];
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}

- (instancetype)init
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super init];
    });
    return instance;
}

//发送服务器请求加载数据
- (void)loadDataFormServer{
    
    NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[kServerUrl stringByAppendingString:@"showusertally.php"]]];
    [quest setHTTPMethod:@"POST"];
    //POST 用户名
    NSString *userName = [[NSUserDefaults standardUserDefaults] objectForKey:@"userName"];
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:userName,@"username", nil];
    NSData *postData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
    [quest setHTTPBody:postData];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionTask *task = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        //json解码
        NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"server下载结果-----%@",dataStr);
        if ([dataStr isEqualToString:@"0"]) {
            return ;
        }
        NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
        if (jsonArray.count != 0) {
            [[CoreDataOperations sharedInstance] loadFromServerWithDataArray:jsonArray];
        }
    }];
    
    [task resume];

}

//上传账单至服务器
- (void)uploadTallyToServer{
    NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[kServerUrl stringByAppendingString:@"uploadtally.php"]]];
    [quest setHTTPMethod:@"POST"];
    //POST 信息
    NSArray *postArray = [[CoreDataOperations sharedInstance] getAllTallyWithArray];
    NSData *postData = [NSJSONSerialization dataWithJSONObject:postArray options:NSJSONWritingPrettyPrinted error:nil];
    [quest setHTTPBody:postData];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionTask *task = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        int flag = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] intValue];
        NSLog(@"server上传结果 %d",flag);
        if (flag==1 || flag == 9) {
            //写入成功
            for (NSDictionary *dict in postArray) {
                [[CoreDataOperations sharedInstance] uploadServerSucceedWithIdentity:dict[@"identity"]];
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                if ([self.delegate respondsToSelector:@selector(didUploadTallySuccessed)]) {
                    [self.delegate didUploadTallySuccessed];
                }
            });
           
        }else{
            dispatch_async(dispatch_get_main_queue(), ^{
                if ([self.delegate respondsToSelector:@selector(didUploadTallyFaild)]) {
                    [self.delegate didUploadTallyFaild];
                }
            });

        }
        
    }];
    
    [task resume];

}

//登录到服务器
- (void)loginWithUser:(NSString*)username andPsw:(NSString*)psw {
    //创建URL请求
    NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[kServerUrl stringByAppendingString:@"login.php"]]];
    //post请求
    [quest setHTTPMethod:@"POST"];
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:username,@"username",psw,@"userpsw", nil];
    //字典转json
    NSData *postData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
    [quest setHTTPBody:postData];
    
    //建立连接
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionTask *task = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        int result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] intValue];
        NSLog(@"server登录结果 %d ",result);

        dispatch_async(dispatch_get_main_queue(), ^{
            if ([self.delegate respondsToSelector:@selector(didLoginBackWithTag:)]) {
                [self.delegate didLoginBackWithTag:result];
            }
            
        });
        
    }];
    
    [task resume];

}

//注册到服务器
- (void)registerWithUser:(NSString*)username andPsw:(NSString*)psw{
    //创建URL请求
    NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[kServerUrl stringByAppendingString:@"register.php"]]];
    //post请求
    [quest setHTTPMethod:@"POST"];
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:username,@"username",psw,@"userpsw", nil];
    //字典转json
    NSData *postData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
    [quest setHTTPBody:postData];
    
    //建立连接
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionTask *task = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        int result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] intValue];
        NSLog(@"server注册结果 %d ",result);
        //回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            if ([self.delegate respondsToSelector:@selector(didRegisterBackWithTag:)]) {
                [self.delegate didRegisterBackWithTag:result];
            }
        });
    }];
    
    [task resume];
}

//从服务器删除账单
- (void)deleteTallyInServerWithIdentity:(NSString*)identity{
    //创建URL请求
    NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[kServerUrl stringByAppendingString:@"deletetally.php"]]];
    //post请求
    [quest setHTTPMethod:@"POST"];
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:identity,@"identity", nil];
    //字典转json
    NSData *postData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
    [quest setHTTPBody:postData];
    //建立连接
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionTask *task = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        int result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] intValue];
        if (result == 0) {
            NSLog(@"%d server链接数据库失败",result);
        }else if (result == 1){
            NSLog(@"%d server删除账单成功",result);
        }else if (result == 2){
            NSLog(@"%d server删除账单失败",result);
        }
    }];
    
    [task resume];
}
@end

服务端部分

php新手 高手勿喷
文件结构


文件结构

其中index.php 和 useruploadrecords.php是web断的登录展示页面

数据库部分字段和表基本与客户端相同可以看CREATE的代码

代码

配置文件

<?php
define('MYSQL_HOST','localhost');
define('MYSQL_USER','root');
define('MYSQL_PSW','');
define('MYSQL_DBNAME','TimeTally');

所有数据库操作

<?php
require_once 'config.php';

/**链接并选择数据表
 * @param $table 链接表
 * @return mysqli 链接link
 */
function connectDBandSelectTable($table) {
    $con = mysqli_connect(MYSQL_HOST,MYSQL_USER,MYSQL_PSW);
    mysqli_set_charset($con,'utf8');
    if ($con){
        mysqli_select_db($con,MYSQL_DBNAME);
        if(mysqli_num_rows(mysqli_query($con,"SHOW TABLES LIKE '".$table."'"))==0) {
            if ($table == 'Tally'){
                $sql = "CREATE TABLE $table 
                        ( id INT NOT NULL AUTO_INCREMENT , 
                        username VARCHAR(50) NOT NULL ,
                        date VARCHAR(50) NOT NULL , 
                        identity VARCHAR(1024) NOT NULL , 
                        typename VARCHAR(50) NOT NULL , 
                        income DOUBLE NOT NULL , 
                        expenses DOUBLE NOT NULL , 
                        timestamp DOUBLE NOT NULL ,
                        uploadtime TIMESTAMP NOT NULL,
                        PRIMARY KEY (id))";
                mysqli_query($con,$sql);

            }elseif ($table == 'Users'){
                $sql = "CREATE TABLE $table 
                        (id INT  NOT  NULL AUTO_INCREMENT, 
                        username VARCHAR (100) NOT  NULL ,
                        userpsw VARCHAR (100) NOT  NULL , 
                        session INT  NOT  NULL  DEFAULT  0,
                        PRIMARY KEY (id))";
                mysqli_query($con,$sql);
            }
        }
    }
    return $con;
}

/**注册
 * @param $table 表
 * @param $username 用户名
 * @param $userpsw 用户密码
 * @return int 0:连接失败 1:注册成功 2:用户已存在
 */
function register($table,$username,$userpsw){
    $con = connectDBandSelectTable($table);
    if ($con){
        $isExist = existQuery($table,"username",$username);
        if ($isExist == 2){
            $sql = "INSERT INTO $table (username, userpsw) VALUES ('$username',MD5('$userpsw'))";
            $result = mysqli_query($con,$sql);
            if ($result){
                //成功
                return 1;
            }
        }else if ($isExist == 1){
            //已存在
            return 2;
        }
        //关闭数据库
        mysqli_close($con);
    }
    //连接数据库失败
    return 0;
}

/**查询字段是否存在
 * @param $table 表名
 * @param $field 查询字段名
 * @param $obj 查询对象
 * @return 0:连接失败 1:存在 2:不存在
 */
function existQuery($table,$field,$obj){
    $con = connectDBandSelectTable($table);
    if ($con){
        $sql = "SELECT * FROM $table WHERE $field = '$obj'";
        $result = mysqli_query($con,$sql);
        if (mysqli_num_rows($result) > 0){
            return 1;
        }else{
            return 2;
        }
    }
    return 0;
}

/**获取该用户下所有账单
 * @param $table 表名
 * @param $user 用户名
 * @return int|string 0:连接失败或无法查询  string:json数组;
 */
function getUserTally($table,$user){
    $con = connectDBandSelectTable($table);
    if ($con){
        $sql = "SELECT * FROM $table WHERE username = '$user'";
        $arr = mysqli_query($con,$sql);
        $num = mysqli_num_rows($arr);
        if ($num > 0){
            for ($i=0;$i<$num;$i++){
                $results[] = mysqli_fetch_assoc($arr);
            }
            mysqli_close($con);
            return json_encode($results);
        }
    }
    //连接失败或无法查询
    return 0;
}

/**登录验证
 * @param $username 用户名
 * @param $userpsw  用户密码
 * @return int  0:连接失败 1:验证成功 2:密码错误 3:用户不存在
 */
function verifyLogin($username,$userpsw){
    //查询用户名是否存在
    $table = 'Users';
    $con = connectDBandSelectTable($table);
    if ($con){
        $sql = "SELECT * FROM $table WHERE username = '$username'";
        $isExist = mysqli_query($con,$sql);
        if (mysqli_num_rows($isExist) > 0) {
            //存在并继续验证 密码
            $result = mysqli_fetch_array($isExist);
            $psw = $result['userpsw'];
            if (md5($userpsw) == $psw){
                //密码正确
                return 1;
            }else {
                //密码错误
                return 2;
            }

        }else {
            //用户不存在
            return 3;
        }
        mysqli_close($con);
    }

    //数据库连接失败
    return 0;

}

/**上传更新或新增账单数据
 * @param $table  写入表名
 * @param $tallyJson 传入解析后的json
 * @return int -1:数据库连接失败 0:没有写入 1:写入成功 2:写入失败 9:更新数据
 */
function uploadTally($table,$tallyJson){
    $con = connectDBandSelectTable($table);
    $r = 0;
    if ($con){
        //根据json解析出来的数组的长度 更新对应identity数值
        for ($i=0;$i<count($tallyJson);$i++){
            $identity = $tallyJson[$i]->identity;
            $isExistSql = "SELECT * FROM $table WHERE identity LIKE '$identity'";
            $isExisResult = mysqli_query($con,$isExistSql);
            if (mysqli_num_rows($isExisResult) > 0){
                $typename = $tallyJson[$i]->typename;
                $income = $tallyJson[$i]->income;
                $expenses = $tallyJson[$i]->expenses;
                $timestamp = $tallyJson[$i]->timestamp;
                $updateSql = "UPDATE $table 
                          SET typename = '$typename',
                          income='$income' ,
                          expenses = '$expenses',
                          uploadtime = CURRENT_TIMESTAMP,
                          timestamp = '$timestamp'
                          WHERE identity = '$identity'";
                mysqli_query($con,$updateSql);
                $r = 9;
            } else{
                //没有查询到identity则进入新增
                $typename = $tallyJson[$i]->typename;
                $income = $tallyJson[$i]->income;
                $expenses = $tallyJson[$i]->expenses;
                $username = $tallyJson[$i]->username;
                $date = $tallyJson[$i]->date;
                $timestamp = $tallyJson[$i]->timestamp;
                //mysql插入
                $intoSql = "INSERT INTO $table
                          (id,username,date,identity,typename,income,expenses,timestamp,uploadtime)
                          VALUES (NULL, '$username', '$date','$identity','$typename','$income','$expenses','$timestamp',CURRENT_TIMESTAMP)";
                $insertResult = mysqli_query($con,$intoSql);
                if ($insertResult){
                    //新增成功
                   $r = 1;
                }else{
                    //新增失败
                    $r = 2;
                }
            }
        }
    mysqli_close($con);
    }else{
        //连接失败
        $r = -1;
    }
    return $r;
}

/**
 * @param $table 表名
 * @param $identity 需要删除的标识
 * @return int 0:链接数据库失败 1:删除成功 2:删除失败
 */
function deleteTally($table,$identity){
    $con = connectDBandSelectTable($table);
    if ($con){
        $sql = "DELETE FROM $table WHERE identity = '$identity'";
        $result = mysqli_query($con,$sql);
        if ($result){
            return 1;
        }else{
            return 2;
        }
    }
    mysqli_close($con);
    return 0;
}

/**获取post的json数据 并连接数据库表
 * @param $table 表名
 * @return mixed json数据
 */
function getPostJsonValue($table){
//获取post数据
    $postValue = file_get_contents("php://input");
//json解析
    $postJson = json_decode($postValue);
    $currentTable = $table;
//连接并选择数据库
    connectDBandSelectTable($currentTable);
    return $postJson;
}

各个调用页面

登录

<?php
require_once 'dboperations.php';
//获取post数据
$table = 'Users';
$postValue = getPostJsonValue($table);
//登录验证
$result = verifyLogin($postValue->username,$postValue->userpsw);
echo $result;

注册

<?php
require_once 'dboperations.php';
//获取post数据并连接数据库表
$currentTable = 'Users';
$postJson = getPostJsonValue($currentTable);
//注册
$result = register($currentTable,$postJson->username,$postJson->userpsw);
echo $result;

下载服务端数据

<?php
require_once 'dboperations.php';
$table = 'Tally';
$postValue = getPostJsonValue($table);
$reslut = getUserTally($table,$postValue->username);
echo $reslut;

上传

<?php
require_once 'dboperations.php';
$table = 'Tally';
$postJson = getPostJsonValue($table);
$result = uploadTally($table,$postJson);
echo $result;

删除

<?php
require_once 'dboperations.php';
$table = 'Tally';
$postValue = getPostJsonValue($table);
$reslut = deleteTally($table,$postValue->identity);
echo $reslut;

web端

首页登录

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" type="text/css" href="css/style.css" />
    <title>Document</title>
</head>
<body>
<form id="slick-login" action="useruploadrecords.php" method="get" >
    <input type="text" name="username" placeholder="用户名">
    <input type="password" name="userpsw" placeholder="密码">
    <input type="submit" value="Log In"/>
</form>
</body>
</html>

内容页



<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" type="text/css" href="css/tablestyle.css" />
    <title>Document</title>
</head>
<body>
<?php
require_once 'dboperations.php';
if (isset($_GET["username"]) && isset($_GET["userpsw"])){
    $username = $_GET["username"];
    $userpsw = $_GET["userpsw"];
}

$verifty = verifyLogin($username,$userpsw);
if ($verifty == 1){
    $table = 'Tally';
    $con = connectDBandSelectTable($table);
    $sql = "SELECT * FROM $table WHERE username = '$username' ORDER BY uploadtime DESC ";
    $res = mysqli_query($con,$sql);


echo "<table>
<tr><th>欢迎用户:$username</th><th></th><th></th><th></th><th></th></tr>
<tr><th>操作记录</th><th>上传时间</th><th>账单类型</th><th>支出</th><th>收入</th></tr>";
    for ($i=0;$i<mysqli_num_rows($res);$i++){
        $resarray = mysqli_fetch_assoc($res);
        $uploadtime = $resarray["uploadtime"];
        $typename = $resarray["typename"];
        $income= $resarray["income"];
        $expenses = $resarray["expenses"];
        ?>
        <tr>
            <td>
                <?php echo $i+1?>
            </td>
            <td>
                <?php echo $uploadtime?>
            </td>
            <td>
                <?php echo $typename?>
            </td>
            <td>
                <?php echo $expenses?>
            </td>
            <td>
                <?php echo $income?>
            </td>
        </tr>
<?php
    }
echo "</table>";
}elseif ($verifty == 2){

    echo "<script> alert('密码错误');parent.location.href='index.php'; </script>";

}elseif ($verifty == 3){
    echo "<script> alert('用户不存在');parent.location.href='index.php'; </script>";
}
?>
</body>
</html>

Demo地址

https://github.com/gongxiaokai/TimeTallyOnlineDemo
其中包含server端的php代码和客户端的oc代码

github

简书主页

http://www.jianshu.com/u/7897b0bd4a55

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,408评论 4 371
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,690评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,036评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,726评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,123评论 3 296
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,037评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,178评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,964评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,703评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,863评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,333评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,658评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,374评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,195评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,988评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,167评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,970评论 2 279

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,111评论 18 139
  • 转载自cr180大神DiscuzX2.5完整目录结构【source程序文件库】 /source/admincp后台...
    cndaqiang阅读 789评论 1 2
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,598评论 25 707
  • 人生 就是一场电影 你是主角 但却不能主导 不能循环,暂停,停止。 但却可以演绎得无比接近内心 却不能走进心灵深处。
    展翅的鱼阅读 219评论 0 2
  • 正月刚过,天气渐暖,相信很多人的内心开始蠢蠢欲动,思忖着要开始减肥、健身。网上随便一搜就可以搜到很多有关健身、减肥...
    蚕豆小象阅读 429评论 0 8