Write the Code. Change the World.

2月 25

到了今天,还用 php + bootstrap 来做网站已经不是很明智的选择了。可以用 vue,可以用 react 这样会更迅速,更方便。以怀旧的心情,以崇新的心情,还是选择了 laravel10 + bootstrap5 来制作一个官网。
因为看到一个很不错的网站,它的配色和布局都是喜欢的(它是用 react 来构建的)。那就仿着它的效果做下去吧。所以,现在得把 bootstrap 的配色搞定。这个需要去观察和理解 bootstrap 的样式配置。

定义站点配色,组件配色

# 主要色
$primary:#caff04 !default;

输入框配置以及按钮配置

这里截取了部分配置,看得出来,它的配置有一部分还得依赖按钮的配置。当然你也可以单独设置。可是想要整体都统一,还是比较伤脑筋。那按钮也一并处理。

…
$primary: #caff04 !default;

// 输入框的配置
$input-border-color: #000000 !default;
$input-focus-border-color: #000000 !default;
$border-width: 2px !default;
$input-btn-focus-color: $primary !default;
$input-btn-focus-blur: 5px !default;
$input-btn-focus-width: 3px !default;

// 按钮
$input-btn-padding-y: .25rem !default;
$input-btn-padding-x: .75rem !default;
$border-radius: .5rem !default;

如果按照目标站点的按钮样式来弄,比较贴近的按钮类型是 btn-outline。但仅仅改改颜色是不够的。因为他们的 hover,active 的颜色行为不统一。而处理按钮的类型行为(这么理解吧)在源码的 scss/mixins/_buttons.scss 这里。好吧,定义颜色以及圆角这些可以在自己的 _variables 文件中进行,处理 mixins 好像不可以(我自己对整个原理也没理解清楚)。但是修改源码的 scss/mixins/_buttons.scss 编译出来时可以的。这是一种不可取的办法,因为源码是自己下载的,不进行版本控制的。如果源码升级或项目换位置。修改的 scss/mixins/_buttons.scss 将会丢失。暂时还没想到好的解决方法,就先记录在这里。想实现目标按钮的效果。只需下边这样修改即可(注释两行,修改一行)。

// scss-docs-start btn-outline-variant-mixin
@mixin button-outline-variant(
  $color,
  $color-hover: color-contrast($color),
  $active-background: $color,
  $active-border: $color,
  $active-color: color-contrast($active-background)
) {
  --#{$prefix}btn-color: #{$color};
//   --#{$prefix}btn-border-color: #{$color};
     --#{$prefix}btn-border-color: rgba(255,255,255,0);
//   --#{$prefix}btn-hover-color: #{$color-hover};
//   --#{$prefix}btn-hover-bg: #{$active-background};
  --#{$prefix}btn-hover-border-color: #{$active-border};
  --#{$prefix}btn-focus-shadow-rgb: #{to-rgb($color)};
  --#{$prefix}btn-active-color: #{$active-color};
  --#{$prefix}btn-active-bg: #{$active-background};
  --#{$prefix}btn-active-border-color: #{$active-border};
  --#{$prefix}btn-active-shadow: #{$btn-active-box-shadow};
  --#{$prefix}btn-disabled-color: #{$color};
  --#{$prefix}btn-disabled-bg: transparent;
  --#{$prefix}btn-disabled-border-color: #{$color};
  --#{$prefix}gradient: none;
}
// scss-docs-end btn-outline-variant-mixin

可以尝试下这种定制:https://www.bootstrap.cn/doc/read/105.html

若干小时后

仿照目标站点,本来很简单的一个样式。如果用 bootstrap 去实现,就太友好了。这样改的心累。放弃吗。继续。这以上统统算胡言乱语。重新开始,继续 laravel10 + bootstrap5 。

参考

https://getbootstrap.com/docs/5.2/components/buttons/

input 框的配置 https://www.bootstrap.cn/doc/read/124.html

2月 24

linux 下,刚创建的 laravel10 项目,安装了前端脚手架。运行 pnpm run dev 的时候报 System limit for number of file watchers reached 错误。网上说 是linux系统的限制导致这个报错。

解决

sudo vim /etc/sysctl.conf

# 添加以下内容
fs.inotify.max_user_watches=524288

# 保存退出
:wq

# 重新加载系统参数
sudo sysctl -p

# 再执行 pnpm run dev 就不会报错了
2月 20

安装好了 bootstrap,我们先确定好主题色,然后开始创建网站的公用模块(头部和底部)。

前奏

路由调整,功能连贯

我们先删掉默认的 welcome.blade.php 文件和 HomeController 文件。

再创建一个默认的页面控制器,我喜欢叫 PageController,并且是放在 web 文件夹下的。后边会有 api 的控制器,所以才这样分开。

php artisan make:controller web/PageController

# 在里边添加一个方法,输出一个前端页面
/**
 * Show the application dashboard.
 *
 * @return \Illuminate\Contracts\Support\Renderable
 */
public function home()
{
    return view('home');
}

这里,不需要构造器。在之前删除的构造器中有构造器 ,并指定了 auth 的中间件。这样用户只要不是登录态访问页面,都会默认跳转到登录页面。

修改路由文件 web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\web\PageController;

Route::get('/', [PageController::class, 'home'])->name('home');

Auth::routes();

在浏览器访问 http://xr.com 就可以看到顶部带有注册登录按钮的页面了。

本地化(多语言)

这个时候,注册和登录是英文的。是多语言功能没配置好。可以在 resources 下创建 lang 目录,lang 下创建 en 和 zh-CN 目录。里边分别创建 messages.php。然后填充下边的内容。

# en/messages.php
<?php

return [
    'login' => 'Login',
    'register' => 'Register',
    'logout' => 'Logout',
];

# zh-CN/messages.php
<?php

return [
    'login' => '登录',
    'register' => '注册',
    'logout' => '登出',
];

然后 修改 app.blade.php 中的 __('Login') 为 __('messages.login'),再打开站点。

发现英文的已经变成了中文了。

默认,lang 是直接在项目根目录下的,也就是和 resources 同级。个人不喜欢在根目录放太多玩意,就放在 resources 下。
多语言还可以使用 json 文件,还可以配置传参,也可以配置安装包的多语言。更多信息请看官方文档。
https://laravel.com/docs/10.x/localization

这里站点是纯中文的,后边也不考虑英文。就直接删除 lang。以及在 blade 中直接使用中文,不使用多语言调用了。

基本构成(思路)

经过前边的一些调整。我们来好好处理下 app.blade.php 文件。这个是整个站点的灵魂和基础。传统的网站,头部和底部都是公用的,中间区域随着页面不同而不同。这里就单独把头部和底部抽离出来。中间部分定义好插槽即可。这个插槽和 vue 项目中又有不同。理解为占坑就可。可以为 style 样式位置占坑,可以为 html 位置占坑,也可以为 js 占坑。

一点一点的来。

还有一个细节。上述所描述的一个容器,如果遇到页面高度比浏览器窗口的高度小很多的情况呢。页面那么多,看过有的网站在这种情况下。底部之后,会有很大一片空白(页面是从上到下的平面)。这样很难看。在这里,约定父容器的最小高度就是 100vh。页面减去顶部和中间部分的,就是底部的。想办法让顶部和中间撑开到自适应不就看可以了吗。这样会好看一点。后边出一个图。

头部

  1. 头部我喜欢用抽屉式(Offcanvas)。
  2. 头部我预想有一个 logo,几个主菜单,还有搜索框登录注册按钮构成。就是三部分。其实,这里实例中已经给出了结构。

底部

  1. 底部放一列友情链接
  2. 底部放一列联系方式
  3. 底部放一列二维码(最多两个)

上边就是心中所想。然后得用 bootstrap 的结构来表达,并且是融入 laravel 的 blade 中的。

基本构成(文件)

  1. app.blade.php
  2. header.blade.php
  3. footer.blade.php

header.blade.php

这样算比较简洁。因为是官网,不是论坛博客性质的,还是去掉搜索相关功能。还有多语言,也要准备起来。

<header class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
    <div class="container-fluid px-5">
        <a class="navbar-brand" href="{{ url('/') }}">
            Logo
        </a>

        <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar"
            aria-controls="offcanvasNavbar">
            <span class="navbar-toggler-icon"></span>
        </button>

        <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasNavbar" aria-labelledby="offcanvasNavbarLabel">
            <div class="offcanvas-body">
                <ul class="navbar-nav flex-grow-1 px-3 main-nav">
                    <li class="nav-item active">
                        <a class="nav-link" aria-current="page" href="#">首页</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">约拍</a>
                    </li>

                    <li class="nav-item">
                        <a class="nav-link" href="#">瞬间</a>
                    </li>

                    <li class="nav-item">
                        <a class="nav-link" href="#">关于我们</a>
                    </li>
                </ul>

                <ul class="navbar-nav pe-3">
                @guest
                    @if (Route::has('login'))
                        <li class="nav-item">
                            <a class="nav-link" href="{{ route('login') }}">登录</a>
                        </li>
                    @endif

                    @if (Route::has('register'))
                        <li class="nav-item">
                            <a class="nav-link" href="{{ route('register') }}">注册</a>
                        </li>
                    @endif
                @else
                    <li class="nav-item dropdown">
                        <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button"
                            data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                            {{ Auth::user()->name }}
                        </a>

                        <div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                            <a class="dropdown-item" href="{{ route('logout') }}"
                                onclick="event.preventDefault();
                                             document.getElementById('logout-form').submit();">
                                登出
                            </a>

                            <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
                                @csrf
                            </form>
                        </div>
                    </li>
                @endguest
                </ul>
            </div>
        </div>
    </div>
</header>

header.blade.php

这里先空着,占个位置

<footer>

</footer>

app.blade.php

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
</head>
<body>
    <div id="app">
        <main>
            @include('layouts.header')
            @yield('content')
        </main>
        @include('layouts.footer')
    </div>
</body>
</html>

当然,对应的 css 也要的。

我们先在 resources/sass/app.scss 中添加。

# 定义你的主题色
$primary-color: #ECB34D;

html,
body {
    height: 100%;
    color: #000000;
    background: #f4f4f4;
    font-family: "PingFang SC", "微软雅黑", "Microsoft YaHei", Helvetica,
        "Helvetica Neue", Tahoma, Arial, sans-serif;
    font: 14px "PingFang SC", "微软雅黑", "Microsoft YaHei", Helvetica,
        "Helvetica Neue", Tahoma, Arial, sans-serif;
}

a,
a:link,
a:active,
a:hover,
a:visited,
a:focus {
    text-decoration: none;
    list-style: none;
    outline: none;
    cursor: pointer;
}

ul {
    list-style: none;
    list-style-type: none;
}

button:focus,
button:active:focus,
button.active:focus,
button.focus,
button:active.focus,
button.active.focus {
    outline: none;
}

.btn-primary {
    color: #fff !important;
}

#app {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    height: 100%;

    main {
        display: flex;
        flex-direction: column;
        flex: 1 0 auto;
    }
}

header {
    height: 72px;

    // 导航
    .main-nav {
        .nav-item {
            display: flex;
            padding: 7px 16px;
            border-radius: 4px;
            color: #383838;
            margin-right: 16px;

            .nav-link {
                padding: 0 !important;
                background-color: inherit !important;
                font-weight: 300 !important;
                font-size: 16px !important;
                line-height: 20px !important;
                color: #383838;
            }
        }

        .nav-item.active {
            background-color: $primary-color;
        }

        .nav-item.active>.nav-link {
            color: #fff;
        }

        .nav-item:not(.active):hover {
            background-color: $primary-color;
        }

        .nav-item:not(.active):hover>.nav-link {
            color: #fff;
        }
    }
}

footer {
    width: 100%;
    height: 220px;
    background-color: #383838;
}

最后,修改下 home.blade.php

@extends('layouts.app')

@section('content')

<div class="container pt-4">
    <div class="row justify-content-center">
        <h2>home</h2>
    </div>
</div>
@endsection

然后,在打开首页看看。

一些说明

域名其实我自己配置的是 ypb2.com。所以看到的是截图上的样子。 然后访问是 http,上服务器是要配置成 https 的。还有 favicon 也没有配置。以及看代码 keywords 等都没有处理。后边都会要完善的。以及页面的 loading 也没处理。虽然那么多年过去了,还是喜欢用 nprogress 那样的方式。

提交代码

git add .
git commit  -m '处理页面的连接以及基本配置'
2月 18

做网站用 php,做自适应网站用 bootstrap。很早的时候,这是一个不错的组合。喜欢 laravel,那么现在用 laravel10 + bootstrap5 + vue 就不错。

创建一个 laravel 项目

laravel10 release 版本已经发布,可以这样创建

composer create-project laravel/laravel xxx10 --prefer-dist

### 查看当前版本(当前显示 10.0.3)
cd xxx10
php artisan --version

# git 初始化,方便版本管理
git init
git add .
git commit -m 'laravel initialize 10.0.3'

修改配置

这里我 homestead 配置的域名是 xr.com,数据库名是 xr

.env

vim .env
# 修改 APP_URL 以及数据库配置
APP_URL=http://xr.com
DB_DATABASE=xr
DB_USERNAME=homestead
DB_PASSWORD=secret

config/app.php

vim config/app.php

# 修改以下内容
'timezone' => 'Asia/Shanghai',
'locale' => 'zh-CN',
'faker_locale' => 'zh_CN',

添加辅助函数

加辅助函数集,用来安放无副作用的函数。增加到 app 下。

vim app/helpers.php

# 增加一个辅助测试函数
<?php 

    function test($str = 'world') {
        return 'Hello ' . $str;
    }

# 将该文件增加到 composer 的自动加载配置中。 autoload->files 就是需要 composer 自动帮我们加载的函数库(不含类)

vim composer.json

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        },
        "files": [
           "app/helpers.php" 
        ]
    },

# 然后 dump (这一步是不可少的)
composer dump-autoload

加好了之后,就可以来尝试一下了。这里打开 tinker 来试试。

php artisan tinker;

test();

test('bird')

最后,提交代码。

git  add .
git commit -m '修改基础配置以及创建辅助函数集'

安装 ui 包

composer require laravel/ui

php artisan ui bootstrap --auth

# 现在前端就用 pnpm + vite 组合
pnpm install 

pnpm run dev

如果报 System limit for number of file watchers reached 错误,请看 https://blog.vini123.com/837

这样就 ok 了。 注意看 resources/views/layouts/app.blade.php。如果站点效果都统一,可以其他页面都继承该模板。blade 模板真的很好用啊,可以继承,可以重写,可以插槽。

跟随时代的潮流,用上 vite 来构建前端项目。之前,laravel9 就开始使用 vite 来构建了。

因为是自己构建的,所以可以定义一些 bootstrap 的一些特征。比如 primary 的颜色。这样就很爽。

# resources/sass/_variables.scss 中,在尾部追加下边的代码(这样你的 primary 色就是红色了 。),当然还有更多的定义。

$primary: #f00;

https://v5.bootcss.com/docs/customize/color/

https://www.runoob.com/bootstrap5/bootstrap5-colors.html

相关

vite 中文文档 https://cn.vitejs.dev/guide/

bootstrap5 中文文档:https://v5.bootcss.com/docs/getting-started/introduction/

bootstrap5 教程 https://www.runoob.com/bootstrap5/bootstrap5-tutorial.html

2月 01

先下载 mysql8,这里我们选择社区免费版。

https://dev.mysql.com/downloads/

版本选择
https://www.jianshu.com/p/d038a139ba9f

cmake 完整选项列表参考: https://dev.mysql.com/doc/refman/8.0/en/source-configuration-options.html

其实,下载按照下边这个链接里边的地址就可以。更换一下版本号,都是源码包下载安装的。这个是带 boost 的。
https://blog.vini123.com/380

cmake 选项表:

cmake ../ -DCMAKE_INSTALL_PREFIX=/alidata/service/mysql/mysql -DMYSQL_DATADIR=/alidata/service/mysql/data -DWITH_BOOST=boost -DSYSCONFDIR=/etc -DFORCE_INSOURCE_BUILD=1 -DDEFAULT_CHARSET=utf8mb4 -DDEFAULT_COLLATION=utf8mb4_general_ci -DENABLED_LOCAL_INFILE=ON -DWITH_INNODB_MEMCACHED=ON -DWITH_FEDERATED_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITHOUT_EXAMPLE_STORAGE_ENGINE=1

在 mysql8 源码包下,另建 build 文件夹,然后执行 camke 操作。

可能会有的错误信息。根据输出信息,安装非常不建议在源码包下面直接编译。如果在其他目录下,对于同一份源码,你可以执行和生成多份cmake builds。并且可以简易地cleanup,即删除build目录即可。这个错误在MySQL5.7和MariaDB的源码编译过程中并不会碰到,应该是新的8.0版本的改进之一了。其用意感觉应该是为了方便系统管理员在一份源码下灵活地安装多份配置各异的MySQL实例。但在本地自己安装用的时候,并不需要考虑这么多,cmake时按照提示添加“ -DFORCE_INSOURCE_BUILD=1 ”选项即可。

后边继续:

2月 01

视频以及动画是一个比较好的视觉体验。可是,移动端 h5 的 video 标签不能自动播放视频。下边总结下处理方案。其实,就是在网上找到别人的解决方案来解决自己的事情。

处理处理

video 标签

<video class="video" poster="xxx.jpg" autoplay loop muted 
        playsinline="true"
        x5-playsinline="true" 
        webkit-playsinline="" 
        x-webkit-airplay="allow" 
        x5-video-player-type="h5"
        preload="auto">
                <source src="xxx.mp4" type="video/mp4">
        </video>

方法1,使用类似 gif 图的方式,来实现是视频播放的效果。

https://blog.csdn.net/qq_33929420/article/details/114962347

方法2,使用 js 来手动处理播放

//其他移动端浏览器只能让用户自己触发
$(window).on('touchstart', function(){
    $("video")[0].play();
});
// 兼容微信(微信可以自动播放)
document.addEventListener("WeixinJSBridgeReady", function () {
    $("video")[0].play();
}, false);