Container

是一个结合了绘制(painting)、定位(positioning)以及尺寸(sizing)widget的widget。
最里层的是child元素

padding 内边距 margin 外边距 Edgelnsets()

decoration BoxDecoration (变框,圆角,渐变,阴影,背景色,背景图片)
alignment 对齐
trasform 变形 Matrix4 (平移 translate rotate scale skew)

默认宽度不是全屏的,可以设置 width: double.infinity

Container({
Key key,
this.alignment,
this.padding,
Color color,
Decoration decoration,
this.foregroundDecoration,
double width,
double height,
BoxConstraints constraints,
this.margin,
this.transform,
this.child,
})

Flex 弹性布局

direction 声明主轴方向

flex 分配占比

流式布局

Wrap 解决内容溢出

Chip 标签
CircleAvatar 圆形头像

import 'package:bitsdojo_window/bitsdojo_window.dart';

void main() {
runApp(const MyApp());
doWhenWindowReady(() {
final win = appWindow;
const initialSize = Size(1024, 768);
win.minSize = initialSize;
win.size = initialSize;
win.alignment = Alignment.center;
win.title = "Custom window with Flutter";
win.show();
});
}

button

ElevatedButton.icon(
icon: const Icon(Icons.add, size: 18),
label: const Text('Login to Github'),
onPressed: () {
print('哈哈');
})


child:
ListView(
children: [
const Text('自选股列表',style: ( TextStyle(
color:Colors.white,fontSize: 18.0
)),)
,
_createDataTable()
]
),

安装 vscode 插件 flutter
要能够编译桌面应用,您必须在特定的平台上编译应用: 在 Windows 上构建 Windows 应用,在 macOS 上构建 macOS 应用,在 Linux 上构建 Linux 应用

// 设置代理就不用下面的操作了
set http_proxy=http://127.0.0.1:7890
set https_proxy=https://127.0.0.1:7890

// 国内不翻墙的话需要使用镜像,设置下面两个环境变量,国内的社区提供的
set PUB_HOSTED_URL=https://pub.flutter-io.cn
set FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
git clone -b dev https://github.com/flutter/flutter.git
export PATH="$PWD/flutter/bin:$PATH"

Shanghai Jiaotong University Linux User Group
set FLUTTER_STORAGE_BASE_URL=https://mirrors.sjtug.sjtu.edu.cn/
set PUB_HOSTED_URL=https://dart-pub.mirrors.sjtug.sjtu.edu.cn/
// 升级
flutter upgrade
// 检查依赖
flutter doctor
// 查看支持哪些平台
flutter devices

flutter config --enable-windows-desktop
// <platform> = linux, windows, macos

// 创建项目
flutter create project_name
// 运行
flutter run -d windows
// 发布程序,路径在windows/runner/releae下面
flutter build windows

// 需要下面的运行库
msvcp140.dll
vcruntime140.dll
vcruntime140_1.dll

使用 IntelliJ IDE

打开插件偏好设置 (位于 File > Settings > Plugins)
选择 Marketplace (扩展商店),选择 Flutter plugin 然后点击 Install (安装)。

创建项目,选择Flutter SDK 路径,然后输入项目名字,main.dart 在 lib 目录下面

快速简要介绍下列三种构建模式:

  1. 开发过程中,需要使用 热重载 功能,请选择 debug 构建模式;
  2. 当你需要分析性能的时候,选择使用 profile 构建模式;
  3. 发布应用的时候,需要选择使用 release 构建模式。

布局

使用代码来构建 UI,widget 是构建 Flutter UI 的基本单元,非常容易组合,这意味着你能够通过组合已有的 widgets 来创造更多复杂的 widgets

Row 和 Column 类
用来容纳和布局 widgets 的类,在它们内部的 widgets 我们称为 children, Row 和 Column 就作为它们的父级。 Row 将会让 widgets 水平排列,而 Column 则会让其竖直排列。
mainAxisAlignment 和 crossAxisAlignment 属性决定了 Row 和 Column在各个轴上如何布局 widget

Flexible widget
当 Flexible widget 包裹 widget 时,这个 widget 就成为 Flexible widget 的子节点,并被视为 flexible 的。在布置固定大小的 widget 后, Flex 的 widget 根据其 flex 和 fit 属性调整大小:

flex
将自身的 flex 因子与其他的比较,以决定自身占剩余空间的比例。

fit
决定 Flexible 的 widget 是否能够填充所有剩余空间。

框架里面有两个最主要的 Widget 类:StatefulWidget 和 StatelessWidget。

许多 Widget 都是无状态的:它们的属性不随着时间改变。这样的 Widget 是 StatelessWidget 的子类。
如果 Widget 的某个特征需要根据用户交互或者其他因素发生改变,那么这种 Widget 是 StatefulWidget。

通用布局

标准 widgets
Container:向 widget 增加 padding、margins、borders、background color 或者其他的“装饰”。
GridView:将 widget 展示为一个可滚动的网格。
ListView:将 widget 展示为一个可滚动的列表。
Stack:将 widget 覆盖在另一个的上面。

Material widgets
Card:将相关信息整理到一个有圆角和阴影的盒子中。
ListTile:将最多三行的文本、可选的导语以及后面的图标组织在一行中。

widget

main->runApp->MyApp->MaterialApp->Scaffold

material Icon等资源官网

干的豆腐丝
热水泡软后,煮熟2分钟左右,胡萝卜丝,青椒丝,圆葱丝,放入凉水中,然后淋干
蒜末,芝麻,小米辣,辣椒粉,热油浇上, 盐,白糖,香油,生抽,醋,鸡精

小葱葱白和叶子分开 切葱花,
葱白+芝麻+辣椒粉+蒜末

花椒油炸后捞出,分三次导入葱白混合物中,每倒一次就用勺子搅拌一下,最后放入葱叶花,搅拌均匀。

使用 docker 配置服务

export the below variables in terminal

export http_proxy=’http://192.168.0.107:7890'
export https_proxy=’https://192.168.0.107:7890'
and use the following commands to disable proxy

unset http_proxy
unset https_proxy

// 设置docker代理,在创建容器的时候自动配置进去
// C:\Users\Dev\.docker\config.json
{
"proxies":
{
"default":
{
"httpProxy": "http://192.168.0.107:7890",
"httpsProxy": "http://192.168.0.107:7890",
"noProxy": "*.xx.example.com,.xx2.com,127.0.0.0/8"
}
}
}

sudo apt update -y
// remove old version first
sudo apt-get remove docker docker-engine docker.io containerd runc

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
// 避免每次 docker 命令都需要 sudo
// 创建名为docker的组,如果之前已经有该组就会报错,可以忽略这个错误:
// sudo groupadd docker
// 将当前用户加入组docker
sudo gpasswd -a ${USER} docker
// 重启docker服务
sudo systemctl restart docker
// 添加访问和执行权限
sudo chmod a+rw /var/run/docker.sock

// install redis
sudo docker pull redis
sudo docker pull redis:alpine
sudo docker run -p 6379:6379 --name kvm-redis -d redis
// 终端访问 确认运行正常
sudo docker exec -it kvm-redis bash
// ash for alpine version
sudo docker exec -it kvm-redis ash
redis-cli
// Get a list of keys registered in redis
keys *
// 停止容器运行
sudo docker stop kvm-redis
// 删除容器
sudo docker rm kvm-redis
Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: TLS handshake timeout
网络慢,多试几次就可以了,或者添加一个国内的镜像源
docker pull mysql:5.7.39
// 默认配置运行
sudo docker run -p 3306:3306 --name kvm-mysql -e MYSQL_ROOT_PASSWORD=lanbe123 -d mysql:5.7
// 进入docker bash
docker exec -it kvm-mysql bash
// 找到配置文件路径
mysql --help | grep my.cnf

mysql -u root -p
// 查看 data 路径 /var/lib/mysql/
show variables like '%datadir%';
// 拷贝容器配置文件
sudo docker cp kvm-mysql:/etc/my.cnf .

// windows
docker run --name kvm-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=lanbe123 --mount type=bind,src=C:/Users/Dev/Documents/1/mysql/conf/my.cnf,dst=/etc/my.cnf --mount type=bind,src=C:/Users/Dev/Documents/1/mysql/data,dst=/var/lib/mysql --restart=on-failure:3 -d mysql:5.7.39

// 导入 sql
docker cp monitor.sql kvm-mysql:/monitor.sql
// 进入docker bash
docker exec -it kvm-mysql bash
mysql -uroot -planbe123 --default-character-set=utf8mb4
create database monitor character set utf8mb4;
drop database monitor;
// 导入 sql
mysql -uroot -planbe123 -D monitor < monitor.sql

//on-failure:3 是指容器在未来出现异常退出(退出码非0)的情况下循环重启3次

// 删掉容器重新开始
sudo docker stop kvm-mysql
sudo docker start kvm-mysql
sudo docker rm kvm-mysql

// 重启容器
docker container restart kvm-mysql

asp.net core 部署

可以在项目创建完成以后在添加Dockerfile文件,在项目上右键,选择“添加”选项下面的“Docker支持”
然后选择Linux系统
docker build -t kvm-api-service .
// 默认里面监听的是 80 端口
docker run --name=kvm-api -p 52000:80 -d kvm-api-service

docker exec -it kvm-api bash

vue部署

// docker file
FROM nginx:stable-alpine
ADD ./dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]


docker build -t kvm-front:vue2 .
docker run --name kvm-front -p 52100:80 -v C:\Users\Dev\Documents\1\nginx\data\:/var/log/nginx -d kvm-front:vue2
docker exec -it kvm-front ash

nginx

// 默认路径
conf
/etc/nginx/nginx.conf
html
/usr/share/nginx/html
log
/var/log/nginx


docker pull nginx:stable-alpine

docker run --name nginx-proxy -p 8080:8080 -v C:\Users\Dev\Documents\1\nginx\conf\nginx.conf:/etc/nginx/nginx.conf -d nginx:stable-alpine
docker exec -it kvm-proxy ash

// 加入网络
--net=kvm-net


// 检查配置文件
docker exec nginx-base nginx -t
// 重新加载配置文件
docker exec nginx-base nginx -s reload


导出、导入镜像

// 导出容器
docker export kvm-api > kvm-api.tar
// 导入容器
docker import - kvm-api-service < kvm-api.tar

// 导出镜像 ID
docker save [options] images [images...]
docker save -o filename.tar <repo>:<tag>

// 导出镜像 使用 repo:tag 如果只用 id 会导致 导入时没有 repo:tag 信息
docker save kvm-api-service:latest > kvm-api-image.tar
// 同时多个镜像打包
docker save -o images.tar postgres:9.6 mongo:3.4
// 载入镜像
docker load < hangge_server.tar

docker compose

docker compose 批量启动服务,可以理解为管理容器的批处理命令

// 开始构建镜像并启动服务
docker compose up
// -d 以后台守护进程模式启动 -p 项目名称 网络名称也是这个
docker compose up -d -p kvmService
// 停止运行中的容器
docker compose down
// 开始运行容器
docker compose start
// 重新构建容器
docker compose build

docker compose ps
// 网络信息
docker network ls

部分 compose.yaml 样例

# Expose ports without publishing them to the host machine - they'll only
# be accessible to linked services. Only the internal port can be specified.
expose:
- "3000"
- "8000"
# Expose ports. Either specify both ports (HOST:CONTAINER), or just the
# container port (a random host port will be chosen).
#
# Note: When mapping ports in the HOST:CONTAINER format, you may experience
# erroneous results when using a container port lower than 60, because YAML
# will parse numbers in the format xx:yy as sexagesimal (base 60). For this
# reason, we recommend always explicitly specifying your port mappings as
# strings.
ports:
- "3000"
- "8000:8000"
- "49100:22"
- "127.0.0.1:8001:8001"
# Mount paths as volumes, optionally specifying a path on the host machine
# (HOST:CONTAINER), or an access mode (HOST:CONTAINER:ro).
volumes:
- /var/lib/mysql
- cache/:/tmp/cache
- ~/configs:/etc/configs/:ro
# Mount all of the volumes from another service or container.
volumes_from:
- service_name
- container_name
# A single value, analogous to its docker run counterpart.
working_dir: /code

docker file 是一个文本文件,每一个指令都会建立一层,最好使用 && 将各个所需命令串联起来放到一层里面

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

FROM 指定基础镜像
RUN 指令是用来执行命令行命令的
RUN [“可执行文件”, “参数1”, “参数2”]

docker build -t nginx:v3 .

–mount 参数的 type=bind 表明要挂载的共享目录

ENTRYPOINT

ENTRYPOINT has two forms:

The exec form, which is the preferred form:

ENTRYPOINT [“executable”, “param1”, “param2”]

The shell form:

ENTRYPOINT command param1 param2

//导出全部站点的方法:
%windir%/system32/inetsrv/appcmd list site /config /xml > sites.xml
//导出所有应用程序池的方法
%windir%/system32/inetsrv/appcmd list apppool /config /xml > apppools.xml

//导入应用程序池的方法:
%windir%/system32/inetsrv/appcmd add apppool /in < apppools.xml
//导入站点的方法:
%windir%/system32/inetsrv/appcmd add site /in < sites.xml

使用 nginx 做反向代理,监听 80 端口,/ 转发给 vue 10002 端口,/v1 转发给 asp.net core 的 48326 端口

asp.net

//在Startup中的ConfigureServices里增加
services.AddSession();
services.AddCors(options =>
{
options.AddPolicy("cors", builder =>
{
// 注意 有 80 和 没 80 是不同的
builder.AllowAnyOrigin().WithOrigins("*", "http://localhost", "http://127.0.0.1", "http://localhost:80", "http://127.0.0.1:80")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();//指定处理cookie
});
});

services.AddControllers();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
//修改配置,防止页面切换后session ID改变(默认是改变的,Seesion会失效)
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;//这里要改为false,默认是true,true的时候session无效
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// 解决 反向代理时的 session id 变化问题
services.AddDataProtection();

//在Configure里增加:
app.UseCors("cors");
app.UseSession();

vue

也可以在调试的时候使用 proxy ,但是生产环境用不了,所以最好调试环境和生产环境保持一致。

const instance = axios.create({
withCredentials: true
});

配置后台 IP

// 编辑.env.development文件 配置 api 地址
# base api
VUE_APP_BASE_API = 'http://localhost:10002'

// 修改vue.config.js
devServer: {
port: port,
open: true,
overlay: {
warnings: false,
errors: true
},
proxy: {
// change xxx-api/login => mock/login
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
target: process.env.VUE_APP_BASE_API,
changeOrigin: true, //配置跨域
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
// 这个注释掉
//after: require('./mock/mock-server.js')

npm run build

动态配置服务端IP