# 健行科技大學 網頁全端養成班 上課筆記
## 專題
#### 第一組
組長: 09田秉弘
組員: 23卓子坤
24鄭皓陽
13游玄安
12楊亞承
#### 第二組
組長: 袁達新
組員: 鄭郁珊
組員: 徐晟詠
組員: 李宜璋
#### 第三組
主題:3C購物網站
08:高宏溢-組長
04:王弘毅
#### 第四組
主題: 旅行社RWD動態網頁
組長: 29 楊明璋
組員: 29 楊明璋
#### 第五組
##### 組長
20.鍾鴻見
##### 組員名單:
25. 王楷仁
02. 陳正沛
20. 鍾鴻見
10. 林彥廷
11. 葉政豪
#### 第六組
組長:楊芸軒
#### 第七組
組長:林均
組員:呂旻玲
組員:方聖傑
組員:陳廷銘
組員:彭信淵
組員:李文伶
#### 第八組
主題: 露營用品專賣店網頁
組長: 21 蔡文瑞
組員: 21 蔡文瑞
#### 第九組
專題: 3C購物網站
22:汪世傑組長
## 2024-09-05
#### 將後端以系統服務的方式執行
編寫: /etc/systemd/system/my-backend.service
```bash=
[Unit]
Description=my-backend
[Service]
WorkingDirectory=/var/www/my-backend
ExecStart=/var/www/my-backend/my-backend
Restart=always
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=my-backend
[Install]
WantedBy=multi-user.target
```
#### 讓系統認識你的服務
```bash=
$ systemctl daemon-reload
```
#### 讓服務生效
```bash=
$ systemctl enable my-backend
```
#### 啟動服務
```bash=
$ systemctl start my-backend
```
#### 停止服務
```bash=
$ systemctl stop my-backend
```
#### 重新啟動服務
```bash=
$ systemctl restart my-backend
```
#### 查詢Console.WriteLine()輸出的訊息
```bash=
$ journalctl -u my-backend
```
#### 查詢服務狀態
```bash=
$ systemctl status my-backend
```
#### GCP
GCE免費的條件: https://cloud.google.com/free/docs/free-cloud-features#compute
#### MacOS產生金鑰方式
```
$ ssh-keygen -t rsa -f ~/.ssh/user -C user
```
#### ssh連線到雲端
1. 打開putty
2. Host name: {username}@{public IP}
3. 設定Private Key: Connection->SSH->Auth->Credintals->第一個框要選擇剛剛儲存的Private Key
#### MacOS ssh連線
```
$ chmod 600 ~/.ssh/{account}
$ ssh -r -i ~/.ssh/{account} {account}@{ip}
```
#### SCP前端
```bash=
$ scp -i C:\Users\User\Documents\gcp.pem dist/* aaron@34.168.94.105:/var/www/html
```
> 下這行指令之前請記得先`chmod 777 /var/www/html`
#### SCP後端
```bash=
$ scp -i C:\Users\User\Documents\gcp.pem bin\Release\net8.0\linux-x64\publish\* aaron@34.168.94.105:/var/www/my-backend
```
#### Database Dump
```sql=
-- MySQL dump 10.13 Distrib 5.5.62, for Win64 (AMD64)
--
-- Host: 192.168.77.128 Database: shop
-- ------------------------------------------------------
-- Server version 8.0.39-0ubuntu0.24.04.2
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `account`
--
DROP TABLE IF EXISTS `account`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `account` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`phone` varchar(32) DEFAULT NULL,
`create_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `account`
--
LOCK TABLES `account` WRITE;
/*!40000 ALTER TABLE `account` DISABLE KEYS */;
INSERT INTO `account` VALUES (1,'aaron','0987654321','2024-09-04 01:56:53'),(2,'apple','0912345678','2024-09-04 00:00:00');
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2024-09-04 14:58:35
```
## 2024-09-04
#### 安裝mySQL
Ubuntu官方文件: https://ubuntu.com/server/docs/install-and-configure-a-mysql-server
1. 安裝mysql
```
$ sudo apt install mysql-server
```
> root密碼請設複雜一點,因為如果開放到網路會很容易被駭客入侵
2. 確認mysql狀態
```
$ sudo service mysql status
```
3. 檢查mySQL使用了那些port
```
$ sudo netstat -tulpn | grep LISTEN
```
> **備註:**
> 這個指令需要先安裝: `sudo apt install net-tools`
4. 建立遠端連線帳號
```bash=
$ sudo mysql -u root -p
```
```sql=
mysql> CREATE USER 'aaron'@'%' IDENTIFIED BY '0000';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'aaron'@'%' WITH GRANT OPTION;
```
確認帳號是否有建立:
```sql=
mysql> select user from mysql.user;
```
5. 將mySQL綁定到public ip
編輯`/etc/mysql/mysql.conf.d/mysqld.cnf`
修改`bind-address`為你的public IP:
```
bind-address = 192.168.0.5
```
重新啟動mysql:
```sql=
# systemctl restart mysql
```
參考內容:
```
#
# The MySQL database server configuration file.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
# Here is entries for some specific programs
# The following values assume you have at least 32M ram
[mysqld]
#
# * Basic Settings
#
user = mysql
# pid-file = /var/run/mysqld/mysqld.pid
# socket = /var/run/mysqld/mysqld.sock
# port = 3306
# datadir = /var/lib/mysql
# If MySQL is running as a replication slave, this should be
# changed. Ref https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_tmpdir
# tmpdir = /tmp
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 192.168.77.128
mysqlx-bind-address = 127.0.0.1
#
# * Fine Tuning
#
key_buffer_size = 16M
# max_allowed_packet = 64M
# thread_stack = 256K
# thread_cache_size = -1
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover-options = BACKUP
# max_connections = 151
# table_open_cache = 4000
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
#
# Log all queries
# Be aware that this log type is a performance killer.
# general_log_file = /var/log/mysql/query.log
# general_log = 1
#
# Error log - should be very few entries.
#
log_error = /var/log/mysql/error.log
#
# Here you can see queries with especially long duration
# slow_query_log = 1
# slow_query_log_file = /var/log/mysql/mysql-slow.log
# long_query_time = 2
# log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
# other settings you may need to change.
# server-id = 1
# log_bin = /var/log/mysql/mysql-bin.log
# binlog_expire_logs_seconds = 2592000
max_binlog_size = 100M
# binlog_do_db = include_database_name
# binlog_ignore_db = include_database_name
```
> **補充:**
> 免密碼進入mysql
> a. 建立mysql目錄: `sudo mkdir -p /var/run/mysqld`
> b. 將目錄所有權改為mysql: `sudo chown mysql:mysql /var/run/mysqld`
> c. 以安全模式執行mysql: `sudo mysqld_safe --skip-grant-tables &`
> d. 以root身分進入mysql: `mysql -u root`
#### 安裝dbeaver
官網: https://dbeaver.io/

#### 建立.NET API後端專案
```
$ dotnet new webapi -minimal -n my-backend
```
#### 一個簡單的RESTFul 風格API
```csharp=
app.MapGet("/v1/my-first-api", () =>
{
// API要做的事情寫在這裡
return new
{
Code = 0,
Message = "成功",
Data = "這是給你的資料"
};
});
```
#### 本地端測試API
```bash=
$ curl -s http://localhost:5000/v1/my-first-api | jq
```
#### .NET部署到Ubuntu
官方文件: https://learn.microsoft.com/en-us/dotnet/core/deploying/
建置.NET
```bash=
$ dotnet publish -c Release -r linux-x64 --self-contained -p:PublishSingleFile=true
```
到server建立新的目錄:
```bash=
$ cd /var/www
$ mkdir my-backend
$ chmod 777 my-backend
```
透過scp複製剛剛建置好的.NET程式
```bash=
scp bin\Release\net8.0\linux-x64\publish\* aaron@192.168.77.128:/var/www/my-backend
```
#### 讓.NET後端綁定所有IP
###### Program.cs
```bash=
...
app.Run("http://*:5000");
```
> 在Program.cs最後一行
#### .NET連接資料庫
1. 安裝MySqlConnector
```csharp=
$ dotnet add package MySqlConnector.DependencyInjection
```
2. 將MySql加入DI Container
```csharp=
builder.Services.AddMySqlDataSource("Server=192.168.77.128;User ID=aaron;Password=3939889;Database=shop");
```
3. 加上using MySqlConnector
```csharp=
using MySqlConnector;
```
> 加在Program.cs第一行
4. 將MySqlConnection注入API參數
```
app.MapGet("/v1/my-first-api", (MySqlConnection connection) =>
{
// API要做的事情寫在這裡
return new
{
Code = 0,
Message = "成功",
Data = "這是給你的資料"
};
});
```
#### 後端最終版
```csharp=
using MySqlConnector;
var builder = WebApplication.CreateBuilder(args);
// 將MySql加入DI Container
builder.Services.AddMySqlDataSource("Server=192.168.77.128;User ID=aaron;Password=3939889;Database=shop");
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();
app.MapGet("/v1/my-first-api", (MySqlConnection connection) =>
{
// 連線資料庫
connection.Open();
// 準備SQL指令
using var command = new MySqlCommand("SELECT * FROM account;", connection);
// 執行SQL指令
using var reader = command.ExecuteReader();
List<dynamic> allData = new List<dynamic>();
// 讀出每一筆資料
while (reader.Read())
{
var value1 = reader.GetValue(0);
var value2 = reader.GetValue(1);
var value3 = reader.GetValue(2);
var value4 = reader.GetValue(3);
Console.WriteLine($"{value1}|{value2}|{value3}|{value4}");
// 將資料新增到List
allData.Add(new
{
Id = value1,
Name = value2,
Phone = value3,
CreateData = value4
});
}
// API要做的事情寫在這裡
return new
{
Code = 0,
Message = "成功",
Data = allData
};
});
app.Run("http://*:5000");
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
```
> **注意:**
> 如果你發生Authentication plugin 'caching_sha2_password' cannot be loaded錯誤。
> 修改使用者密碼認證方式:
> ```sql=
> ALTER USER 'aaron'@'%' IDENTIFIED WITH mysql_native_password BY '3939889';
> ```
#### 前端串接API
##### 1. NET後端設設定跨域CORS
```csharp=
var builder = WebApplication.CreateBuilder(args);
// 跨域存取設定
builder.Services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
policy =>
{
policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
});
});
```
第二段:
```csharp=
var app = builder.Build();
// 使用CORS跨預設定
app.UseCors("CorsPolicy");
```
##### 2. Vue專案安裝axios套件
```bash=
$ yarn add axios
```
> axios官網: https://axios-http.com/docs/intro
##### 3. 在需要呼叫api的地方引入axios
```javascript=
import axios from 'axios'
import { ref, onMounted } from 'vue'
```
##### 4. 在需要呼叫api的地方使用axios.get()
```javascript=
const el = ref();
// 網頁載入時會觸發的方法
onMounted(() => {
console.log("test");
// Make a request for a user with a given ID
axios.get('http://localhost:5000/v1/my-first-api')
.then(function (response) {
// handle success
// console.log(response);
el.value = response.data.data;
console.log(el.value);
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});
});
```
##### 5. 把收到的資料從response.data拿出來render到網頁上
```javascript=
el.value = response.data.data;
```
範例:
```javascript=
<div class="container">
<div class="table">
<div class="table-header">
<div class="header__item"><a id="name" class="filter__link" href="#">ID</a></div>
<div class="header__item"><a id="wins" class="filter__link filter__link--number" href="#">Name</a></div>
<div class="header__item"><a id="draws" class="filter__link filter__link--number" href="#">Phone</a></div>
<div class="header__item"><a id="losses" class="filter__link filter__link--number" href="#">Create Date</a>
</div>
</div>
<div class="table-content">
<div v-for="value in el" class="table-row">
<div class="table-data">{{ value.id }}</div>
<div class="table-data">{{ value.name }}</div>
<div class="table-data">{{ value.phone }}</div>
<div class="table-data">{{ value.createData }}</div>
</div>
</div>
</div>
</div>
```
樣式:
```css=
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700");
*,
*:before,
*:after {
box-sizing: border-box;
}
body {
padding: 24px;
font-family: "Source Sans Pro", sans-serif;
margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
}
.container {
max-width: 1000px;
margin-right: auto;
margin-left: auto;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.table {
width: 100%;
border: 1px solid #EEEEEE;
}
.table-header {
display: flex;
width: 100%;
background: #000;
padding: 18px 0;
}
.table-row {
display: flex;
width: 100%;
padding: 18px 0;
}
.table-row:nth-of-type(odd) {
background: #EEEEEE;
}
.table-data,
.header__item {
flex: 1 1 20%;
text-align: center;
}
.header__item {
text-transform: uppercase;
}
.filter__link {
color: white;
text-decoration: none;
position: relative;
display: inline-block;
padding-left: 24px;
padding-right: 24px;
}
.filter__link::after {
content: "";
position: absolute;
right: -18px;
color: white;
font-size: 12px;
top: 50%;
transform: translateY(-50%);
}
.filter__link.desc::after {
content: "(desc)";
}
.filter__link.asc::after {
content: "(asc)";
}
```
## 2024-09-02
#### 將身分提升為root系統管理者
```bash=
$ sudo su
```
#### 更新套件管理系統
```bash=
# apt-get update
```
#### 安裝nginx
```bash=
# apt-get install nginx
```
#### 檢查Nginx的服務狀態
```bash=
# systemctl status nginx
```
#### 切換到根目錄
```bash=
# cd /
```
#### 切換到nginx的網頁目錄
```bash=
# cd /var/www/html
```
#### 建立新的目錄
```bash=
# mkdir assets
```
#### 回到上一層目錄
```bash=
# cd ..
```
#### 建立vue專案
1. yarn開發、預覽網頁
2. vite建立專案: https://vitejs.dev/guide/
```bash=
yarn create vite my-vue-app --template vue
```
3. 進入剛建立的專案目錄: `cd my-vue-app`
4. 初始化專案: `yarn`
5. 啟動開發伺服器: `yarn dev`
#### 佈署vue專案到nginx
##### 1. 建置vue專案
```bash=
$ yarn build
```
> **注意:**
> 1. 必須在vue專案目錄下下指令
> 2. 建置完會產生dist目錄
##### 2. 將dist目錄下的檔案scp到遠端
```bash=
$ scp -r dist aaron@192.168.77.128:~
```
> **補充:**
> 1. 該指令會連同dist目錄一起複
> 製過去
> 2. `-r` 代表連同子目錄一起複製過去
##### 3. 將遠端的dist目錄下檔案和子目錄複製到`/var/www/html`下
使用root權限並`cd到`/var/www/html`目錄下:
```bash=
$ sudo su
# cd /var/www/html
# cp -r /home/aaron/dist/* .
```
> **備註:**
> 該指令會將dist目錄下的所有檔案和子目錄複製過去,但是dist目錄本身不會複製過去
##### 4. 完成
到瀏覽器打開網頁就可以看到vue專案建置出來的網頁
## 檔案系統權限介紹
#### 第一個字元代表這個檔案是『目錄、檔案或連結檔等等』:
- d: 目錄。
- -: 檔案。
- l: 連結檔(link file);
- b: 裝置檔裡面的可供儲存的周邊設備(可隨機存取裝置);
- c: 裝置檔裡面的序列埠設備,例如鍵盤、滑鼠(一次性讀取裝置)。
接下來的字元中,以三個為一組,且均為『rwx』 的三個參數的組合。
- r: 代表可讀(read)
- w: 代表可寫(write)
- x: 代表可執行(execute)。
> 這三個權限的位置不會改變,如果沒有權限,則會出現減號。
第一組為『檔案擁有者可具備的權限』。
第二組為『加入此群組之帳號的權限』。
第三組為『非本人且沒有加入本群組之其他帳號的權限』。
#### `chgrp` :改變檔案所屬群組
```
$ chgrp {新的群組名稱} {檔案名稱}
```
#### `chown` :改變檔案擁有者
```
$ chown {新的擁有者名稱} {檔案名稱}
```
#### `chmod` :改變檔案的權限
```
$ chmod 777 {檔案名稱}
```
例如:
```bash=
# chmod 777 html
```
#### `chomd -R`可以遞迴修改權限
```bash=
# chmod -R 777 *
```
### vue-router
SPA虛擬出網址的元件
#### 1. 安裝vue-router
```bash=
$ yarn add vue-router@4
```
> **參考:**
> https://router.vuejs.org/installation
#### 2. 修改App.vue
```html=
<script setup>
</script>
<template>
<RouterView />
</template>
<style scoped>
</style>
```
#### 3. 建立HomeView.vue
```html=
<template>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<HelloWorld msg="我的Vue專案你好" />
<div>Hello</div>
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>
```
#### 4. 建立CardView.vue
```html=
<template>
<div class="body">
<div class="container">
<div class="wrapper">
<div class="banner-image"> </div>
<h1> Toyota Supra</h1>
<p>Lorem ipsum dolor sit amet, <br />
consectetur adipiscing elit.</p>
</div>
<div class="button-wrapper">
<button class="btn outline">DETAILS</button>
<button class="btn fill">BUY NOW</button>
</div>
</div>
</div>
</template>
<script setup>
</script>
<style scoped>
@import url('https://fonts.googleapis.com/css2?family=Righteous&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@300&display=swap');
.body {
/* solid background */
background: rgb(0, 212, 255);
/* gradient background*/
background: linear-gradient(45deg, rgba(0, 212, 255, 1) 0%, rgba(11, 3, 45, 1) 100%);
/* photo background */
background-image: url(https://images.unsplash.com/photo-1619204715997-1367fe5812f1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1889&q=80);
background-size: cover;
background-position: center;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.container {
backdrop-filter: blur(16px) saturate(180%);
-webkit-backdrop-filter: blur(16px) saturate(180%);
background-color: rgba(17, 25, 40, 0.25);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.125);
padding: 38px;
filter: drop-shadow(0 30px 10px rgba(0, 0, 0, 0.125));
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.wrapper {
width: 100%;
height: 100%;
}
.banner-image {
background-image: url(https://images.unsplash.com/photo-1641326201918-3cafc641038e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1887&q=80);
background-position: center;
background-size: cover;
height: 300px;
width: 100%;
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.255)
}
h1 {
font-family: 'Righteous', sans-serif;
color: rgba(255, 255, 255, 0.98);
text-transform: uppercase;
font-size: 2.4rem;
}
p {
color: #fff;
font-family: 'Lato', sans-serif;
text-align: center;
font-size: 0.8rem;
line-height: 150%;
letter-spacing: 2px;
text-transform: uppercase;
}
.button-wrapper {
margin-top: 18px;
}
.btn {
border: none;
padding: 12px 24px;
border-radius: 24px;
font-size: 12px;
font-size: 0.8rem;
letter-spacing: 2px;
cursor: pointer;
}
.btn+.btn {
margin-left: 10px;
}
.outline {
background: transparent;
color: rgba(0, 212, 255, 0.9);
border: 1px solid rgba(0, 212, 255, 0.6);
transition: all .3s ease;
}
.outline:hover {
transform: scale(1.125);
color: rgba(255, 255, 255, 0.9);
border-color: rgba(255, 255, 255, 0.9);
transition: all .3s ease;
}
.fill {
background: rgba(0, 212, 255, 0.9);
color: rgba(255, 255, 255, 0.95);
filter: drop-shadow(0);
font-weight: bold;
transition: all .3s ease;
}
.fill:hover {
transform: scale(1.125);
border-color: rgba(255, 255, 255, 0.9);
filter: drop-shadow(0 10px 5px rgba(0, 0, 0, 0.125));
transition: all .3s ease;
}
</style>
```
#### 5. 建立router規則
```javascript=
import { createWebHistory, createRouter } from 'vue-router'
import HomeView from './pages/HomeView.vue'
import CardView from './pages/CardView.vue'
const routes = [
{ path: '/', component: HomeView },
{ path: '/card', component: CardView },
]
const router = createRouter({
history: createWebHistory(),
routes,
});
// 將router export出去
export default {
router
}
```
> **參考:**
> https://router.vuejs.org/guide/
#### 6. 將router設定給vue
main.js
```javascript=
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
createApp(App).use(router.router).mount('#app')
```
#### 7. 調整nginx
```bash=
# cd /etc/nginx/sites-available
# vim default
```
找到`location {`這行,然後將裡面的設定替換成:
```bash=
try_files $uri $uri/ /index.html;
```
> **參考:**
> https://router.vuejs.org/guide/essentials/history-mode.html#nginx
#### 8. 重新啟動nginx
```bash=
# systemctl restart nginx
```
#### deploy.bat
```bash=
yarn build & scp -r dist/* aaron@192.168.77.128:/var/www/html
```
## 2024-08-30
1. Install OpenSSH Server用來遠端連線用,安裝時必須打勾
#### 檔案與目錄管理指令
- ls: 列出檔案
> -a :全部的檔案,連同隱藏檔( 開頭為 . 的檔案) 一起列出來(常用)
> -A :全部的檔案,連同隱藏檔,但不包括 . 與 .. 這兩個目錄
> -d :僅列出目錄本身,而不是列出目錄內的檔案資料(常用)
> -f :直接列出結果,而不進行排序 (ls 預設會以檔名排序!)
> -F :根據檔案、目錄等資訊,給予附加資料結構,例如:
> *:代表可執行檔; /:代表目錄; =:代表 socket 檔案; |:代表 FIFO 檔案;
> -h :將檔案容量以人類較易讀的方式(例如 GB, KB 等等)列出來;
> -l :長資料串列出,包含檔案的屬性與權限等等資料;(常用)
>-r :將排序結果反向輸出,例如:原本檔名由小到大,反向則為由大到小;
> -R :連同子目錄內容一起列出來,等於該目錄下的所有檔案都會顯示出來;
> -S :以檔案容量大小排序,而不是用檔名排序;
> -t :依時間排序,而不是用檔名。
> --color=never:不要依據檔案特性給予顏色顯示;
> --color=always:顯示顏色
> --color=auto:讓系統自行依據設定來判斷是否給予顏色
> --full-time:以完整時間模式 (包含年、月、日、時、分) 輸出
> --time={atime,ctime} :輸出 access 時間或改變權限屬性時間 (ctime) 而非內容變更時間 (modification time)
- touch: 建立檔案
例如:
```bash=
$ touch test.txt
```
會建立`test.txt`檔案
- vim: 打開檔案並編輯
例如:
```bash=
$ vim test.txt
```
打開`test.txt`檔案
> vim打開檔案預設會在命令模式(command mode)
> `i`或`o`進入插入模式(insert mode)
> `ESC`離開編輯模式回到命令模式(command mode)
> `:`進入底線命令模式(last line mode)
> 在底線命令模式輸入`wq`+`Enter`儲存並離開vim
- cat: 檢視檔案內容
例如:
```bash=
$ cat test.txt
```
會顯示`test.txt`檔案內容
- exit: 登出或離開
- ip: 查看電腦的IP
例如:
```bash=
$ ip a
```
- 遠端登入Linux Server
1. 打開命令提示字元
2. 輸入: `ssh {帳號}:{server ip}`
例如:
```
$ ssh aaron@113.12.9.1
```
3. 第一次登入會詢問是否要紀錄憑證,輸入: yes
4. 輸入你的密碼
5. 完成
- `>`重新導向(覆蓋原始內容)
例如:
```bash=
$ cat > aaron.txt
```
可以在畫面上輸入文字,最後會存到aaron.txt檔案,如果檔案存在,會覆蓋
- `>>`重新導向(在原始內容最後面新增)
例如:
```bash=
$ cat >> aaron.txt
```
可以在畫面上輸入文字,最後會存到aaron.txt檔案,如果檔案存在,會從最後面新增
- `tr`刪除內容
例如:
```
$ cat > a.txt
aaron test1
aaron test2
aaron test3
aaron test4
aaron test5
```
新增一個a.txt檔案
```bash=
$ cat a.txt | tr -d "aaron " > b.txt
```
將a.txt內容透過管線給tr將`aaron `文字刪除後再存到b.txt
- `cp`檔案複製
例如:
```bash=
$ cp a.txt b.txt
```
將檔案a.txt複製為b.txt
- `scp`遠端複製
例如:
```bash=
$ scp a.txt aaron@172.19.115.40:~
```
將檔案a.txt複製到遠端的Home目錄下
```bash=
$ scp aaron@172.19.115.40:~/aaron.txt aaron.txt
```
將遠端Home目錄檔案a.txt複製到本地端的目前路徑下
> Windows下可以安裝WinSCP圖形化工具來作為遠端檔案交換的工具
> https://winscp.net/eng/download.php