首页 > 数据库 >基于WPF+Sqlite开发抽奖软件【内附源码】

基于WPF+Sqlite开发抽奖软件【内附源码】

时间:2024-05-22 17:40:49浏览次数:22  
标签:DataM index Sqlite 抽奖 内附 所示 源码 var INTEGER

在很早之前,就想过开发一款抽奖软件,却一直没有实际去做,最近经过一段时间的准备,终于开发出了一款基于WPF+Sqlite版的抽奖软件,包括客户端和管理端。本项目主要是为了熟悉WPF开发流程,仅供学习分享使用,如有不足之处,还请指正。

 

涉及知识点

 

抽奖软件是包括客户端和管理端,在抽奖软件开发过程中,主要用到了如下知识点:

  • 开发工具:Visual Studion 2022
  • 开发框架:.NET6.0 + WPF
  • MVVM框架:CommunityToolkit.Mvvm 8.2.2
  • 数据库:Sqlite
  • ORM框架:SqlSugarCore 5.1.4.154
  • 数据库客户端:SQLiteStudio 3.4.4

 

数据表设计

 

根据抽奖软件的功能进行拆解,主要包括:Gift(礼品表),Lucky(奖品表),User(抽奖用户表),Winner(中奖表),各个表详细创建语句如下所示:

Gift(礼品表),主要包括礼品名称,图片路径等,如下所示:

CREATE TABLE gift (
    Id       INTEGER       PRIMARY KEY AUTOINCREMENT,
    Name     VARCHAR (255),
    ImageUrl VARCHAR (255) 
);

Lucky(奖品表),主要包括,奖品名称,数量,对应礼品ID,奖品等级(如:一等奖,二等奖),奖品类型,奖品排序(抽奖顺序),如下所示:

CREATE TABLE lucky (
    Id         INTEGER      PRIMARY KEY AUTOINCREMENT,
    Name       VARCHAR (50),
    Count      INTEGER,
    GiftId     INTEGER,
    Level      INTEGER,
    LuckyType  VARCHAR (50),
    LuckyOrder INTEGER
);

 User(抽奖用户表),参与抽奖的用户,主要用户的名称,如下所示:

CREATE TABLE user (
    Id   INTEGER      PRIMARY KEY AUTOINCREMENT,
    Name VARCHAR (50) 
);

 Winner(中奖表),主要包括中奖用户ID,奖品ID,中奖时间等。如下所示:

CREATE TABLE winner (
    Id         INTEGER  PRIMARY KEY AUTOINCREMENT,
    userid     INTEGER,
    luckyid    INTEGER,
    winnertime DATETIME
);

 

功能设计

 

抽奖软件主要包括客户端,和管理端,主要功能如下:

  • 客户端,主要用于抽奖,包括首页,抽奖页面【Enter键开始和停止抽奖,Next键切换奖项】,结束语页面。
  • 管理端,主要用于管理数据信息,包括用户管理,礼品管理,奖品管理,中奖管理等功能,主要是对各个数据表的增删改查。

 

核心源码

 

本实例项目虽然比较小,但作为一个完整的项目,为了层次清晰及便于维护,采用MVVM开发模式,UI和业务逻辑分层处理,并单独封装DAL层。

 

1. 抽奖页面源码

 

整个项目最核心的就是抽奖页面,UI层代码如下所示:

<UserControl x:Class="EasyLucky.Views.Lucky"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
             xmlns:local="clr-namespace:EasyLucky.Views"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="1000">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding LoadedCommand}" PassEventArgsToCommand="True" ></i:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseDown">
                <i:InvokeCommandAction Command="{Binding MouseDownCommand}" PassEventArgsToCommand="True" ></i:InvokeCommandAction>
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Border Grid.ColumnSpan="2" Grid.RowSpan="3">
            <Image Source="/imgs/BG_12.jpg"  Stretch="Fill"></Image>
        </Border>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="0 40 0 0" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center">
            <TextBlock Text="正在抽取的是 " FontSize="40" Foreground="White" VerticalAlignment="Center"></TextBlock>
            <TextBlock Text="{Binding DataM.CurLucky.Lucky.Level}" FontSize="60" Foreground="Gold" FontWeight="DemiBold"></TextBlock>
            <TextBlock Text=" 等奖,共 " FontSize="40" Foreground="White" VerticalAlignment="Center"></TextBlock>
            <TextBlock Text="{Binding DataM.CurLucky.Lucky.Count}" FontSize="60" Foreground="Gold" FontWeight="DemiBold"></TextBlock>
            <TextBlock Text=" 名" FontSize="40" Foreground="White" VerticalAlignment="Center"></TextBlock>
        </StackPanel>
        <ItemsControl Grid.Row="1" Grid.Column="0" ItemsSource="{Binding DataM.CurUsers}" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.DataM.Column}" Rows="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.DataM.Row}" >
                    </UniformGrid>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="40" FontWeight="DemiBold" Foreground="White" Margin="30"></TextBlock>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        
        <StackPanel Margin="100 0 0 10" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">
                    <TextBlock Text="{Binding DataM.CurLucky.Lucky.Level}" FontSize="40" Foreground="Gold" FontWeight="DemiBold" VerticalAlignment="Center"></TextBlock>
                    <TextBlock Text=" 等奖奖品" FontSize="40" Foreground="White" VerticalAlignment="Center"></TextBlock>
                </StackPanel>
                <TextBlock Text="{Binding DataM.CurLucky.Gift.Name}" FontSize="40" Grid.Row="1" Grid.Column="0" Foreground="Gold" FontWeight="DemiBold" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
                <Image Margin="20 0 0 0" Source="{Binding DataM.CurLucky.Gift.ImageSource}" Stretch="Fill" Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Width="200" Height="150"></Image>
            </Grid>
        </StackPanel>
        <TextBlock x:Name="btn" Grid.Column="1" Grid.Row="2" Background="Transparent" Width="10" Height="10" Focusable="True" HorizontalAlignment="Right" VerticalAlignment="Bottom">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="KeyDown">
                    <i:InvokeCommandAction Command="{Binding KeyDownCommand}" PassEventArgsToCommand="True"></i:InvokeCommandAction>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBlock>
    </Grid>
</UserControl>

 

2. 业务逻辑源码

 

业务逻辑代码在ViewModel 中,如下所示:

 

开始抽奖,通过Enter键触发:

private void Start()
{
	cts = new CancellationTokenSource();
	token = cts.Token;
	task = Task.Run(() =>
	{
		var luckyCount = this.DataM.CurLucky.Lucky.Count;
		var userCount = this.DataM.Users.Count;
		var random = new Random(DateTime.Now.Second);
		var rnd = random.Next(0,userCount);
		int index = rnd;
		if(index+luckyCount > userCount)
		{
			index = userCount - luckyCount;
		}
		
		while (!token.IsCancellationRequested)
		{
			var users=new List<User>();
			if(index+luckyCount > userCount)
			{
				//读到最后再循环读取
				for(int i = index; i < userCount; i++)
				{
					users.Add(this.DataM.Users[i]);
				}
				for(int i = 0; i < luckyCount - (userCount - index); i++)
				{
					users.Add(this.DataM.Users[i]);
				}
				index = luckyCount - (userCount - index);
			}
			else
			{
				//顺序读取
				for (int i = index; i < index+luckyCount; i++)
				{
					users.Add(this.DataM.Users[i]);
				}
				index=index+luckyCount;
			}
			Application.Current.Dispatcher.Invoke(new Action(() =>
			{
				this.DataM.CurUsers = new ObservableCollection<User>(users);
			}));
			Thread.Sleep(100);
		}
	},token);
	this.DataM.State = 1;
}

 

停止抽奖 ,并保存中奖结果:

private void Stop()
{
	cts.Cancel();
	//获取当前获奖名单
	var users = this.DataM.CurUsers.ToList();
	var lucky = this.DataM.CurLucky.Lucky;
	if (winnerDal == null)
	{
		winnerDal = new WinnerDal();
	}
	foreach(var user in users)
	{
		var entity = new WinnerEntity()
		{
			UserId = user.Id,
			LuckyId = lucky.Id,
			WinnerTime = DateTime.Now,
		};
		int id= this.winnerDal.AddWinner(entity);
		if(id <1)
		{
			MessageBox.Show("添加失败");
			break;
		}
	}
	//
	for(int i=0; i<users.Count; i++)
	{
		var user = users[i];
		this.DataM.Users.Remove(user);//从列表中移除中奖名单
	}
	this.DataM.State=0;
}

 

下一个奖项,按照奖项顺序选择下一个奖项,通过Next键触发,如下所示:

private void Next()
{
	int order = this.DataM.CurLucky.Lucky.LuckyOrder;
	var next = this.DataM.Luckys.FirstOrDefault(item => item.LuckyOrder > order);
	if (next != null)
	{
		this.DataM.CurLucky.Lucky = next;
		var giftId = this.DataM.CurLucky.Lucky.GiftId;
		this.DataM.CurLucky.Gift = this.DataM.Gifts.FirstOrDefault(item => item.Id == giftId);
		if (next.Count > 4)
		{
			this.DataM.Row = 2;
			this.DataM.Column = (int)Math.Ceiling(next.Count * 1.0d / 2);
		}
		this.DataM.State = 0;
		this.DataM.CurUsers.Clear();
	}
	else
	{
		WeakReferenceMessenger.Default.Send(new StateChangedMessage(2));
	}
}

 

效果演示

 

抽奖软件实例演示,客户端主要包括首页,抽奖页,结束页,如下所示:

 

首页实例

 

抽奖页面

 

结束语页面

 

管理端主要是对数据的管理,包括礼品管理,用户管理,奖项管理,中奖管理,属于常规的数据管理页面,如下所示:

 

源码下载

 

1. gitee下载

 

源码已上传至gitee,用户可通过gitee链接进行下载,如下所示:
项目链接:https://gitee.com/ahsiang/easy-lucky

 

2. 关键字下载

 

关注个人公众号,回复关键字Lucky即可,如下所示:

以上就是基于WPF+Sqlite开发抽奖软件实例的全部内容,希望可以抛砖引玉,一起学习,共同进步。

标签:DataM,index,Sqlite,抽奖,内附,所示,源码,var,INTEGER
From: https://www.cnblogs.com/hsiang/p/18205190

相关文章

  • 安卓-SQLite-基础知识-全-
    安卓SQLite基础知识(全)原文:zh.annas-archive.org/md5/C362B2CF2341EAB7AC3F3FDAF20E2012译者:飞龙协议:CCBY-NC-SA4.0前言Android可能是本十年的热词。在短短的时间内,它已经占据了大部分手机市场。Android计划在今年秋天通过AndroidL版本接管可穿戴设备、我们的电视......
  • N 年前,为了学习分库分表,我把 Cobar 源码抄了一遍
    10几年前,互联网产业蓬勃发展,相比传统IT企业,互联网应用每天会产生海量的数据。如何存储和分析这些数据成为了当时技术圈的痛点,彼时,分库分表解决方案应运而生。当时最流行的Java技术论坛是javaeye,有位淘宝的技术人员分享了一篇分库分表的文章,这篇文章,我反复看了几十遍,想从......
  • CyberRT_不同的启动方式的源码解读
    源码解读componentnodereader/writerservice/clientparameterscheduletransportapollo/cyber/cyber.ccCreateNode(){returnstd::unique_ptr<Node>(newNode(node_name,name_space))}apollo/cyber/init.ccInit() OnShutdown()apollo/cyber......
  • Kubernetes:kubelet 源码分析之探针
    0.前言kubernetes提供三种探针,配置探针(Liveness),就绪探针(Readiness)和启动(Startup)探针判断容器健康状态。其中,存活探针确定什么时候重启容器,就绪探针确定容器何时准备好接受流量请求,启动探针判断应用容器何时启动。本文通过分析kubelet源码了解kubernetes的探针是怎么工作......
  • Kubernetes:kubelet 源码分析之 pod 创建流程
    0.前言kubelet是运行在Kubernetes节点上的“节点代理”,用来管理节点。kubelet主要负责所在节点上的资源对象的管理,例如Pod资源对象的创建,删除,监控,驱逐及生命周期管理等。1.kubelet源码分析1.1kubelet模块kubelet包括的模块如下图:从图中可以看出,kubelet的模......
  • 排队叫号系统项目源码开发搭建
    一款基于PHP开发的多项目多场景排队叫号系统,支持大屏幕投屏,语音播报叫号,可用于餐厅排队取餐、美甲店排队取号、排队领取、排队就诊、排队办理业务等诸多场景,助你轻松应对各种排队取号叫号场景。采用GatewayWorker开发完成的 程序开发:PHP+MySQL程序演示:http://jh1.yetukeji.t......
  • Sqlite 介绍及应用
    1.1.1.1 数据库介绍软件采用SQLITE数据库作为核心管理软件,SQLite数据库以其高效、轻便的特性,在全球范围内得到了广泛的应用。SQLite数据库最大支持128TB,这种数据库支持标准的SQL语言,但与其他数据库管理系统相比,它不需要运行在客户端-服务器架构上,所有的数据都存储在一个本地文件......
  • cmake以源码的方式引入第三方项目
    最前#本文将介绍一种以源码的方式引入第三方库的方法准备#主项目,需要引用第三方库的某些函数第三方库,以源码的形式提供给主项目使用注意:本文的背景:已经将第三方源码下载好。一个例子#我这里准备一个简单的项目,调用第三方库 fmt;其中fmt是以源码的形式引入项目cmake......
  • MySQL全文索引源码剖析之Insert语句执行过程
    本文分享自华为云社区《MySQL全文索引源码剖析之Insert语句执行过程》,作者:GaussDB数据库。1.背景介绍全文索引是信息检索领域的一种常用的技术手段,用于全文搜索问题,即根据单词,搜索包含该单词的文档,比如在浏览器中输入一个关键词,搜索引擎需要找到所有相关的文档,并且按相关性......
  • lodash已死?radash库方法介绍及源码解析 —— 函数柯里化 + Number篇
    写在前面tips:点赞+收藏=学会!主页有更多其他篇章的方法,欢迎访问查看。本篇我们继续介绍radash中函数柯里化和Number相关的方法使用和源码解析。函数柯里化chain:创建一个函数链并依次执行使用说明功能描述:用于创建一个函数链,该链依次执行一系列函数,每个函数的输出......