tiny server.
2
.gitignore
vendored
@ -4,6 +4,8 @@
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||
|
||||
flower.db
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
|
62
App/Constants.cs
Normal file
@ -0,0 +1,62 @@
|
||||
namespace Blahblah.FlowerStory;
|
||||
|
||||
public sealed class Constants
|
||||
{
|
||||
public const string CategoryOther = "other";
|
||||
public const string EventUnknown = "unknown";
|
||||
|
||||
public const SQLite.SQLiteOpenFlags Flags =
|
||||
SQLite.SQLiteOpenFlags.ReadWrite |
|
||||
SQLite.SQLiteOpenFlags.Create |
|
||||
SQLite.SQLiteOpenFlags.SharedCache;
|
||||
|
||||
private const string databaseFilename = "flowerstory.db3";
|
||||
public static string DatabasePath => Path.Combine(FileSystem.AppDataDirectory, databaseFilename);
|
||||
|
||||
public static readonly Dictionary<int, string> Categories = new()
|
||||
{
|
||||
[0] = CategoryOther,
|
||||
[1] = "cactus", // 仙人球
|
||||
[2] = "hibiscus", // 扶桑花
|
||||
[3] = "bougainvillea", // 三角梅
|
||||
[4] = "sunflower", // 太阳花
|
||||
[5] = "milanflower", // 米兰花
|
||||
[6] = "jasmine", // 茉莉花
|
||||
[7] = "periwinkle", // 长春花
|
||||
[8] = "nasturtium", // 旱金莲
|
||||
[9] = "mirabilis", // 紫薇花
|
||||
[10] = "tigerthornplum", // 虎刺梅
|
||||
[11] = "geranium", // 天竺葵
|
||||
[12] = "ballorchid", // 球兰
|
||||
[13] = "medalchrysanthemum", // 勋章菊
|
||||
[14] = "dianthus", // 石竹
|
||||
[15] = "fivecolorplum", // 五色梅
|
||||
[16] = "fuchsia", // 倒挂金钟
|
||||
[17] = "bamboocrabapple", // 竹节海棠
|
||||
[18] = "impatiens", // 凤仙花
|
||||
[19] = "beautysakura", // 美女樱
|
||||
[20] = "petunias", // 矮牵牛
|
||||
[21] = "desertrose", // 沙漠玫瑰
|
||||
[22] = "trailingcampanula", // 蔓性风铃花
|
||||
[23] = "chineserose", // 月季花
|
||||
};
|
||||
|
||||
public static readonly Dictionary<int, Event> Events = new()
|
||||
{
|
||||
[0] = new(EventUnknown),
|
||||
[1] = new("buy", true), // 购买
|
||||
[2] = new("born", true), // 出生
|
||||
[3] = new("changebasin"), // 换盆
|
||||
[4] = new("watering"), // 浇水
|
||||
[5] = new("fertilize"), // 施肥
|
||||
[6] = new("germination"), // 发芽
|
||||
[7] = new("blossom"), // 开花
|
||||
[8] = new("fallenleaves"), // 落叶
|
||||
[9] = new("prune"), // 修剪
|
||||
[10] = new("sick"), // 生病
|
||||
[11] = new("death", true), // 死亡
|
||||
[12] = new("sell", true), // 出售
|
||||
};
|
||||
}
|
||||
|
||||
public record Event(string Name, bool Unique = false);
|
44
App/Data/FlowerDatabase.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using Blahblah.FlowerStory.Data.Model;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SQLite;
|
||||
|
||||
namespace Blahblah.FlowerStory.Data;
|
||||
|
||||
public class FlowerDatabase
|
||||
{
|
||||
private SQLiteAsyncConnection database;
|
||||
|
||||
private readonly ILogger logger;
|
||||
public FlowerDatabase(ILogger<FlowerDatabase> logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
if (database is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);
|
||||
|
||||
#if DEBUG
|
||||
var result =
|
||||
#endif
|
||||
await database.CreateTablesAsync<FlowerItem, RecordItem>();
|
||||
|
||||
#if DEBUG
|
||||
foreach (var item in result.Results)
|
||||
{
|
||||
logger.LogDebug("create table {table}, result: {result}", item.Key, item.Value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public async Task<List<FlowerItem>> GetFlowers()
|
||||
{
|
||||
await Init();
|
||||
return await database.Table<FlowerItem>().ToListAsync();
|
||||
}
|
||||
}
|
45
App/Data/Model/FlowerItem.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using SQLite;
|
||||
|
||||
namespace Blahblah.FlowerStory.Data.Model;
|
||||
|
||||
[Table("flowers")]
|
||||
public class FlowerItem
|
||||
{
|
||||
[Column("fid"), PrimaryKey, AutoIncrement]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("categoryid")]
|
||||
public int CategoryId { get; set; }
|
||||
|
||||
private string categoryName;
|
||||
public string CategoryName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (categoryName == null)
|
||||
{
|
||||
if (!Constants.Categories.TryGetValue(CategoryId, out categoryName))
|
||||
{
|
||||
categoryName = Constants.CategoryOther;
|
||||
}
|
||||
// TODO: i18n
|
||||
}
|
||||
return categoryName;
|
||||
}
|
||||
}
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("datebuy")]
|
||||
public DateTimeOffset DateBuy { get; set; }
|
||||
|
||||
[Column("cost")]
|
||||
public decimal? Cost { get; set; }
|
||||
|
||||
[Column("purchase")]
|
||||
public string Purchase { get; set; }
|
||||
|
||||
[Column("photo")]
|
||||
public byte[] Photo { get; set; }
|
||||
}
|
46
App/Data/Model/RecordItem.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using SQLite;
|
||||
|
||||
namespace Blahblah.FlowerStory.Data.Model;
|
||||
|
||||
[Table("records")]
|
||||
public class RecordItem
|
||||
{
|
||||
[Column("rid"), PrimaryKey, AutoIncrement]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("eid")]
|
||||
public int EventId { get; set; }
|
||||
|
||||
private string eventName;
|
||||
public string EventName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (eventName == null)
|
||||
{
|
||||
if (Constants.Events.TryGetValue(EventId, out var @event))
|
||||
{
|
||||
eventName = @event.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventName = Constants.EventUnknown;
|
||||
}
|
||||
// TODO: i18n
|
||||
}
|
||||
return eventName;
|
||||
}
|
||||
}
|
||||
|
||||
[Column("date")]
|
||||
public DateTimeOffset Date { get; set; }
|
||||
|
||||
[Column("byuid")]
|
||||
public int? ByUserId { get; set; }
|
||||
|
||||
[Column("byname")]
|
||||
public string ByUserName { get; set; }
|
||||
|
||||
[Column("photo")]
|
||||
public byte[] Photo { get; set; }
|
||||
}
|
11
App/Data/Model/UserItem.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Blahblah.FlowerStory.Data.Model;
|
||||
|
||||
public class UserItem
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public int Level { get; set; }
|
||||
public DateTimeOffset RegisterDate { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Mobile { get; set; }
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0-android;net7.0-ios</TargetFrameworks>
|
||||
<TargetFrameworks>net7.0-android</TargetFrameworks>
|
||||
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Blahblah.FlowerStory</RootNamespace>
|
||||
@ -25,24 +25,26 @@
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">23.0</SupportedOSPlatformVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net7.0-android|AnyCPU'">
|
||||
<RuntimeIdentifiers>android-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net7.0-android|AnyCPU'">
|
||||
<AndroidPackageFormat>apk</AndroidPackageFormat>
|
||||
<RuntimeIdentifiers>android-arm64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>android-arm64;android-x64</RuntimeIdentifiers>
|
||||
<AndroidCreatePackagePerAbi>True</AndroidCreatePackagePerAbi>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'=='net7.0-ios'">
|
||||
<CreatePackage>false</CreatePackage>
|
||||
<CodesignProvision>Automatic</CodesignProvision>
|
||||
<ProvisioningType>manual</ProvisioningType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net7.0-ios|AnyCPU'">
|
||||
<CreatePackage>false</CreatePackage>
|
||||
<CodesignProvision>Automatic</CodesignProvision>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net7.0-ios|AnyCPU'">
|
||||
<CreatePackage>false</CreatePackage>
|
||||
<CodesignProvision>Automatic</CodesignProvision>
|
||||
<CodesignKey>iPhone Distribution</CodesignKey>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
@ -69,5 +71,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
|
||||
<PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
</Project>
|
50
App/MainPage.xaml.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using Blahblah.FlowerStory.Data;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Blahblah.FlowerStory
|
||||
{
|
||||
public partial class MainPage : ContentPage
|
||||
{
|
||||
int count = 0;
|
||||
readonly FlowerDatabase database;
|
||||
|
||||
private readonly ILogger logger;
|
||||
public MainPage(FlowerDatabase database, ILogger<MainPage> logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
|
||||
this.database = database;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnCounterClicked(object sender, EventArgs e)
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count == 1)
|
||||
CounterBtn.Text = $"Clicked {count} time";
|
||||
else
|
||||
CounterBtn.Text = $"Clicked {count} times";
|
||||
|
||||
SemanticScreenReader.Announce(CounterBtn.Text);
|
||||
}
|
||||
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = await database.GetFlowers();
|
||||
logger.LogInformation("got {count} flowers.", list.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError("error occurs, {exception}", ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Blahblah.FlowerStory.Data;
|
||||
#if DEBUG
|
||||
using Microsoft.Extensions.Logging;
|
||||
#endif
|
||||
|
||||
namespace Blahblah.FlowerStory
|
||||
{
|
||||
@ -22,6 +25,9 @@ namespace Blahblah.FlowerStory
|
||||
builder.Logging.AddDebug();
|
||||
#endif
|
||||
|
||||
builder.Services.AddSingleton<MainPage>();
|
||||
builder.Services.AddSingleton<FlowerDatabase>();
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
67
Doc/Flower Story - Database.md
Normal file
@ -0,0 +1,67 @@
|
||||
# Flower Story - Database
|
||||
|
||||
## users
|
||||
| column | type | isnull | description |
|
||||
|---------- |--------------|:------:|-------------|
|
||||
| uid | unique int | no |
|
||||
| id | text | no | 用户 id
|
||||
| password | text | no | 加盐密码 [<sup>1</sup>](#ref-anchor-1)
|
||||
| level | integer | no | 用户级别 [<sup>2</sup>](#ref-anchor-2)
|
||||
| regdate | numeric | no | 注册日期
|
||||
| activedate | numeric | | 最后活跃日期
|
||||
| name | text | no | 用户名称
|
||||
| email | text | | 邮箱
|
||||
| mobile | text | | 联系电话
|
||||
---
|
||||
1. <span id="ref-anchor-1"></span>密码存储为 `sha256(password + uid + salt)`
|
||||
2. <span id="ref-anchor-2"></span>级别暂定如下
|
||||
* -1: disabled
|
||||
* 0: user
|
||||
* 99: admin
|
||||
---
|
||||
|
||||
## categories
|
||||
| column | type | isnull | description |
|
||||
|---------- |--------------|:------:|-------------|
|
||||
| cid | unique int | no |
|
||||
| name | text | no | 花草种类名称
|
||||
---
|
||||
|
||||
## flowers
|
||||
| column | type | isnull | description |
|
||||
|---------- |--------------|:------:|-------------|
|
||||
| fid | unique int | no |
|
||||
| categoryid | integer | no | 种类 id
|
||||
| name | text | no | 花草名称
|
||||
| datebuy | numeric | no | 购买时间
|
||||
| cost | real | | 金额
|
||||
| purchase | text | | 购入渠道
|
||||
| photo | blob | | 靓照 [<sup>3</sup>](#ref-anchor-3)
|
||||
---
|
||||
3. <span id="ref-anchor-3"></span>若数据为 `NULL`,则读取 `/assets/$uid/photos/$fid.jpg` 显示为购买时的照片
|
||||
---
|
||||
|
||||
## events
|
||||
| column | type | isnull | description |
|
||||
|---------- |--------------|:------:|-------------|
|
||||
| eid | unique int | no |
|
||||
| name | text | | 事件名称 [<sup>4</sup>](#ref-anchor-4)
|
||||
| unique | integer | | 是否唯一 [<sup>5</sup>](#ref-anchor-5)
|
||||
---
|
||||
4. <span id="ref-anchor-4"></span>事件名称,如购买、出生、换盆、浇水、施肥、发芽、开花、落叶、修剪、生病、死亡、出售等等
|
||||
5. <span id="ref-anchor-5"></span>事件是否唯一,如购买、出生、死亡、出售这些事件具有唯一性
|
||||
---
|
||||
|
||||
## records
|
||||
| column | type | isnull | description |
|
||||
|---------- |--------------|:------:|-------------|
|
||||
| rid | unique int | no |
|
||||
| eid | integer | no | 事件 id
|
||||
| date | numeric | no | 事件发生日期
|
||||
| byuid | integer | | 操作人 uid
|
||||
| byname | text | | 操作人 [<sup>6</sup>](#ref-anchor-6)
|
||||
| photo | blob | | 事件照片 [<sup>7</sup>](#ref-anchor-7)
|
||||
---
|
||||
6. <span id="ref-anchor-6"></span>操作人名称,不是必须为系统内的人员
|
||||
7. <span id="ref-anchor-7"></span>若数据为 `NULL`,则读取 `/assets/$uid/photos/rid/*.jpg` 显示为该事件关联的照片
|
||||
---
|
@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.7.33711.374
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlowerStory", "FlowerStory\FlowerStory.csproj", "{A2EB9F7A-8BB8-4D6D-989C-21C6CF10CE4C}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FlowerStory", "App\FlowerStory.csproj", "{A2EB9F7A-8BB8-4D6D-989C-21C6CF10CE4C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{A551F94A-1997-4A20-A1E8-157050D92CEF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -17,6 +19,10 @@ Global
|
||||
{A2EB9F7A-8BB8-4D6D-989C-21C6CF10CE4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A2EB9F7A-8BB8-4D6D-989C-21C6CF10CE4C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A2EB9F7A-8BB8-4D6D-989C-21C6CF10CE4C}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{A551F94A-1997-4A20-A1E8-157050D92CEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A551F94A-1997-4A20-A1E8-157050D92CEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A551F94A-1997-4A20-A1E8-157050D92CEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A551F94A-1997-4A20-A1E8-157050D92CEF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -1,24 +0,0 @@
|
||||
namespace Blahblah.FlowerStory
|
||||
{
|
||||
public partial class MainPage : ContentPage
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnCounterClicked(object sender, EventArgs e)
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count == 1)
|
||||
CounterBtn.Text = $"Clicked {count} time";
|
||||
else
|
||||
CounterBtn.Text = $"Clicked {count} times";
|
||||
|
||||
SemanticScreenReader.Announce(CounterBtn.Text);
|
||||
}
|
||||
}
|
||||
}
|
12
Server/.config/dotnet-tools.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "7.0.5",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
60
Server/Controller/UserController.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using Blahblah.FlowerStory.Server.Data;
|
||||
using Blahblah.FlowerStory.Server.Data.Model;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Controller
|
||||
{
|
||||
[ApiController]
|
||||
[Route("users")]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private readonly FlowerDatabase database;
|
||||
private readonly ILogger<UserController> logger;
|
||||
|
||||
public UserController(FlowerDatabase db, ILogger<UserController> logger)
|
||||
{
|
||||
database = db;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
[Route("query")]
|
||||
[HttpGet]
|
||||
public ActionResult<UserItem[]> GetUsers()
|
||||
{
|
||||
//var forecast = Enumerable.Range(1, 5).Select(index =>
|
||||
// new WeatherForecast
|
||||
// {
|
||||
// Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
// TemperatureC = Random.Shared.Next(-20, 55),
|
||||
// Summary = summaries[Random.Shared.Next(summaries.Length)]
|
||||
// })
|
||||
// .ToArray();
|
||||
//return Ok(forecast);
|
||||
return Ok(database.Users.ToArray());
|
||||
}
|
||||
|
||||
[Route("update")]
|
||||
[HttpPost]
|
||||
public ActionResult<int> UpdateUser([FromBody] UserItem item)
|
||||
{
|
||||
if (item.Id > 0)
|
||||
{
|
||||
database.Update(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
database.Add(item);
|
||||
}
|
||||
var count = database.SaveChanges();
|
||||
if (count > 0)
|
||||
{
|
||||
logger.LogInformation("{number} of entries written to database.", count);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogWarning("no data written to database.");
|
||||
}
|
||||
return Ok(item.Id);
|
||||
}
|
||||
}
|
||||
}
|
15
Server/Data/FlowerDatabase.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Blahblah.FlowerStory.Server.Data.Model;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Data;
|
||||
|
||||
public class FlowerDatabase : DbContext
|
||||
{
|
||||
public FlowerDatabase(DbContextOptions<FlowerDatabase> options) : base(options) { }
|
||||
|
||||
public DbSet<UserItem> Users { get; set; }
|
||||
|
||||
public DbSet<FlowerItem> Flowers { get; set; }
|
||||
|
||||
public DbSet<RecordItem> Records { get; set; }
|
||||
}
|
32
Server/Data/Model/FlowerItem.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Data.Model;
|
||||
|
||||
[Table("flowers")]
|
||||
public class FlowerItem
|
||||
{
|
||||
[Column("fid"), Key, Required]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("categoryid"), Required]
|
||||
public int CategoryId { get; set; }
|
||||
|
||||
[Column("name"), Required]
|
||||
public required string Name { get; set; }
|
||||
|
||||
[Column("datebuy"), Required]
|
||||
public long DateBuyUnixTime { get; set; }
|
||||
|
||||
[Column("cost", TypeName = "real")]
|
||||
public decimal? Cost { get; set; }
|
||||
|
||||
[Column("purchase")]
|
||||
public string? Purchase { get; set; }
|
||||
|
||||
[Column("photo")]
|
||||
public byte[]? Photo { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateTimeOffset DateBuy => DateTimeOffset.FromUnixTimeMilliseconds(DateBuyUnixTime);
|
||||
}
|
29
Server/Data/Model/RecordItem.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Data.Model;
|
||||
|
||||
[Table("records")]
|
||||
public class RecordItem
|
||||
{
|
||||
[Column("rid"), Key, Required]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("eid"), Required]
|
||||
public int EventId { get; set; }
|
||||
|
||||
[Column("date"), Required]
|
||||
public long DateUnixTime { get; set; }
|
||||
|
||||
[Column("byuid")]
|
||||
public int? ByUserId { get; set; }
|
||||
|
||||
[Column("byname")]
|
||||
public string? ByUserName { get; set; }
|
||||
|
||||
[Column("photo")]
|
||||
public byte[]? Photo { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateTimeOffset Date => DateTimeOffset.FromUnixTimeMilliseconds(DateUnixTime);
|
||||
}
|
32
Server/Data/Model/UserItem.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Data.Model;
|
||||
|
||||
[Table("users")]
|
||||
public class UserItem
|
||||
{
|
||||
[Column("uid"), Key, Required]
|
||||
public int Id { get; set; }
|
||||
[Column("id"), Required]
|
||||
public required string UserId { get; set; }
|
||||
[Column("password"), Required]
|
||||
public required string Password { get; set; }
|
||||
[Column("level"), Required]
|
||||
public int Level { get; set; }
|
||||
[Column("regdate"), Required]
|
||||
public long RegisterDateUnixTime { get; set; }
|
||||
[Column("activedate")]
|
||||
public long? ActiveDateUnixTime { get; set; }
|
||||
[Column("name"), Required]
|
||||
public required string Name { get; set; }
|
||||
[Column("email")]
|
||||
public string? Email { get; set; }
|
||||
[Column("mobile")]
|
||||
public string? Mobile { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateTimeOffset RegisterDate => DateTimeOffset.FromUnixTimeMilliseconds(RegisterDateUnixTime);
|
||||
[NotMapped]
|
||||
public DateTimeOffset? ActiveDate => ActiveDateUnixTime == null ? null : DateTimeOffset.FromUnixTimeMilliseconds(ActiveDateUnixTime.Value);
|
||||
}
|
141
Server/Migrations/20230522090224_InitialCreateDb.Designer.cs
generated
Normal file
@ -0,0 +1,141 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Blahblah.FlowerStory.Server.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Migrations
|
||||
{
|
||||
[DbContext(typeof(FlowerDatabase))]
|
||||
[Migration("20230522090224_InitialCreateDb")]
|
||||
partial class InitialCreateDb
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.5");
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.FlowerItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("fid");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("categoryid");
|
||||
|
||||
b.Property<decimal?>("Cost")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("cost");
|
||||
|
||||
b.Property<DateTimeOffset>("DateBuy")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("datebuy");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<byte[]>("Photo")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("photo");
|
||||
|
||||
b.Property<string>("Purchase")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("purchase");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("flowers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.RecordItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rid");
|
||||
|
||||
b.Property<int?>("ByUserId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("byuid");
|
||||
|
||||
b.Property<string>("ByUserName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("byname");
|
||||
|
||||
b.Property<DateTimeOffset>("Date")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<int>("EventId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("eid");
|
||||
|
||||
b.Property<byte[]>("Photo")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("photo");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("records");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.UserItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("uid");
|
||||
|
||||
b.Property<DateTimeOffset?>("ActiveDate")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("activedate");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("email");
|
||||
|
||||
b.Property<int>("Level")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("level");
|
||||
|
||||
b.Property<string>("Mobile")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("mobile");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("password");
|
||||
|
||||
b.Property<DateTimeOffset>("RegisterDate")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("regdate");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("users");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
83
Server/Migrations/20230522090224_InitialCreateDb.cs
Normal file
@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialCreateDb : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "flowers",
|
||||
columns: table => new
|
||||
{
|
||||
fid = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
categoryid = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
datebuy = table.Column<DateTimeOffset>(type: "numeric", nullable: false),
|
||||
cost = table.Column<decimal>(type: "real", nullable: true),
|
||||
purchase = table.Column<string>(type: "TEXT", nullable: true),
|
||||
photo = table.Column<byte[]>(type: "BLOB", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_flowers", x => x.fid);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "records",
|
||||
columns: table => new
|
||||
{
|
||||
rid = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
eid = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
date = table.Column<DateTimeOffset>(type: "numeric", nullable: false),
|
||||
byuid = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
byname = table.Column<string>(type: "TEXT", nullable: true),
|
||||
photo = table.Column<byte[]>(type: "BLOB", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_records", x => x.rid);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "users",
|
||||
columns: table => new
|
||||
{
|
||||
uid = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
password = table.Column<string>(type: "TEXT", nullable: false),
|
||||
level = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
regdate = table.Column<DateTimeOffset>(type: "numeric", nullable: false),
|
||||
activedate = table.Column<DateTimeOffset>(type: "numeric", nullable: true),
|
||||
name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
email = table.Column<string>(type: "TEXT", nullable: true),
|
||||
mobile = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_users", x => x.uid);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "flowers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "records");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "users");
|
||||
}
|
||||
}
|
||||
}
|
141
Server/Migrations/20230522143925_ChangeDateColumnType.Designer.cs
generated
Normal file
@ -0,0 +1,141 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Blahblah.FlowerStory.Server.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Migrations
|
||||
{
|
||||
[DbContext(typeof(FlowerDatabase))]
|
||||
[Migration("20230522143925_ChangeDateColumnType")]
|
||||
partial class ChangeDateColumnType
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.5");
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.FlowerItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("fid");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("categoryid");
|
||||
|
||||
b.Property<decimal?>("Cost")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("cost");
|
||||
|
||||
b.Property<long>("DateBuyUnixTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("datebuy");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<byte[]>("Photo")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("photo");
|
||||
|
||||
b.Property<string>("Purchase")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("purchase");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("flowers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.RecordItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rid");
|
||||
|
||||
b.Property<int?>("ByUserId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("byuid");
|
||||
|
||||
b.Property<string>("ByUserName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("byname");
|
||||
|
||||
b.Property<long>("DateUnixTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<int>("EventId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("eid");
|
||||
|
||||
b.Property<byte[]>("Photo")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("photo");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("records");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.UserItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("uid");
|
||||
|
||||
b.Property<long?>("ActiveDateUnixTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("activedate");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("email");
|
||||
|
||||
b.Property<int>("Level")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("level");
|
||||
|
||||
b.Property<string>("Mobile")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("mobile");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("password");
|
||||
|
||||
b.Property<long>("RegisterDateUnixTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("regdate");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("users");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
85
Server/Migrations/20230522143925_ChangeDateColumnType.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class ChangeDateColumnType : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "regdate",
|
||||
table: "users",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
oldClrType: typeof(DateTimeOffset),
|
||||
oldType: "numeric");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "activedate",
|
||||
table: "users",
|
||||
type: "INTEGER",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTimeOffset),
|
||||
oldType: "numeric",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "date",
|
||||
table: "records",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
oldClrType: typeof(DateTimeOffset),
|
||||
oldType: "numeric");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "datebuy",
|
||||
table: "flowers",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
oldClrType: typeof(DateTimeOffset),
|
||||
oldType: "numeric");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<DateTimeOffset>(
|
||||
name: "regdate",
|
||||
table: "users",
|
||||
type: "numeric",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "INTEGER");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTimeOffset>(
|
||||
name: "activedate",
|
||||
table: "users",
|
||||
type: "numeric",
|
||||
nullable: true,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "INTEGER",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<DateTimeOffset>(
|
||||
name: "date",
|
||||
table: "records",
|
||||
type: "numeric",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "INTEGER");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTimeOffset>(
|
||||
name: "datebuy",
|
||||
table: "flowers",
|
||||
type: "numeric",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "INTEGER");
|
||||
}
|
||||
}
|
||||
}
|
138
Server/Migrations/FlowerDatabaseModelSnapshot.cs
Normal file
@ -0,0 +1,138 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Blahblah.FlowerStory.Server.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Blahblah.FlowerStory.Server.Migrations
|
||||
{
|
||||
[DbContext(typeof(FlowerDatabase))]
|
||||
partial class FlowerDatabaseModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.5");
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.FlowerItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("fid");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("categoryid");
|
||||
|
||||
b.Property<decimal?>("Cost")
|
||||
.HasColumnType("real")
|
||||
.HasColumnName("cost");
|
||||
|
||||
b.Property<long>("DateBuyUnixTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("datebuy");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<byte[]>("Photo")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("photo");
|
||||
|
||||
b.Property<string>("Purchase")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("purchase");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("flowers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.RecordItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rid");
|
||||
|
||||
b.Property<int?>("ByUserId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("byuid");
|
||||
|
||||
b.Property<string>("ByUserName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("byname");
|
||||
|
||||
b.Property<long>("DateUnixTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<int>("EventId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("eid");
|
||||
|
||||
b.Property<byte[]>("Photo")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("photo");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("records");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Blahblah.FlowerStory.Server.Data.Model.UserItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("uid");
|
||||
|
||||
b.Property<long?>("ActiveDateUnixTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("activedate");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("email");
|
||||
|
||||
b.Property<int>("Level")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("level");
|
||||
|
||||
b.Property<string>("Mobile")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("mobile");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("password");
|
||||
|
||||
b.Property<long>("RegisterDateUnixTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("regdate");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("users");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
36
Server/Program.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using Blahblah.FlowerStory.Server.Controller;
|
||||
using Blahblah.FlowerStory.Server.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Blahblah.FlowerStory.Server;
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllers();
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
builder.Services.AddDbContext<FlowerDatabase>(options => options.UseSqlite("DataSource=flower.db;Cache=Shared"));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseAuthorization();
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
}
|
||||
}
|
31
Server/Properties/launchSettings.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:2132",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5247",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
Server/Server.csproj
Normal file
@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<RootNamespace>Blahblah.FlowerStory.Server</RootNamespace>
|
||||
<UseAppHost>false</UseAppHost>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="flower.db">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
12
Server/WeatherForecast.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Blahblah.FlowerStory.Server;
|
||||
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
|
||||
public string? Summary { get; set; }
|
||||
}
|
8
Server/appsettings.Development.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
9
Server/appsettings.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|