Golang Web 权限设计(简)

https://images.unsplash.com/photo-1627483262268-9c2b5b2834b5?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb

用户与角色

角色设计的意意义可以帮助前端根据权限的不同展示不同的菜单。对于我这个后台就是不同的角色要对应不同的侧边菜单。这里我选择了 antd pro 重组件,他里面有一个 menu 控制侧边栏的展示。我要做的就是设计一个用户模型,一个角色模型,还有一个系统菜单模型,然后通过关联关系将它们联系起来。

这里的难点也许是,你必须要理解前端的动态菜单的生成需要哪些属性。一个菜单包含哪些属性必须由前端来定夺。可以看到antd pro 的动态菜单支持的属性,然后仿照它来设计一个菜单模型。

继续阅读Golang Web 权限设计(简)

一种底部固定上方滚动的H5方案(IOS)

https://images.unsplash.com/photo-1541701494587-cb58502866ab?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb

上下分割思路

上下分割思路总结是指将页面分成上下两部分,一部分是主体滚动页面,一部分是底部固定物件。实现方式上可以分成:可视区域动态获取+CSS变量+UMIJS 全局样式变量三个关键点。

首先是要获取当前我们的可视区。我们不能简单的使用100VH来获取当前视口。因为在移动端100VH的高度这个属性会把上方和下方的导航工具也包含进去这篇文章提到这个问题.。一个计算当前有效视口的函数如下所示。其中,3rem是我指定的一个navbar 的大小这不是巧合,对应tw的h-12原子属性,并定义了 –content-height 这个 CSS 变量,这可以让其他样式根据当前的高度做一个变化。

继续阅读一种底部固定上方滚动的H5方案(IOS)

Antd Upload 上传实战

https://images.unsplash.com/photo-1485827404703-89b55fcc595e?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb

(嫌弃)Form 方式自己组装发送

// 因为涉及到文件上传是单独分开的接口,使用form表单实现
// todo 服务器要拉取当前信息对应的所有附件信息
// 上传 formData <https://blog.csdn.net/TetaiSon/article/details/112677857>
// 自己构建 form data 设定 request 方法 post form
// 关键是知道 upload 的 file 就是一个 Blob list
let formData = new FormData();

Object.keys(newRecord).forEach((key) => {
  if (key !== 'upload') {
    formData.append(key, newRecord[key]);
  } else {
    // file 单独处理
    newRecord.upload?.forEach((file) => {
      formData.append('uploadFiles', file.originFileObj as any);
    });
  }
});

file.originFileObj 是 ANTD 封装的关键,另外,通过append 构造 form 数组。此外你要实现上传的逻辑。相比来说还是下面这种方法简洁。

继续阅读Antd Upload 上传实战

umi + antd-pro 精简化流程

深度使用 antd pro 和 umi 的组合之后,我想自己对这个框架进行控制,脚手架搭建出来的那些乱七八糟的就不要了。在精简过程中,有一些小技巧,故记录在此。

安装 umi

npx @umijs/create-umi-app

安装插件

想在菜单中用字符串指定 icon 需要安装 umi-plugin-antd-icon-config 这个插件进行转换。

修改配置

config/config.ts

import routes from './routes';

import { defineConfig } from 'umi';
export default defineConfig({
  // https://github.com/umijs/umi-plugin-antd-icon-config
  plugins: ['umi-plugin-antd-icon-config'],
  nodeModulesTransform: {
    type: 'none',
  },
  routes,

  fastRefresh: {},
  dva: {
    hmr: true,
    immer: true,
  },
});
继续阅读umi + antd-pro 精简化流程

独立开发的阶段性体会

Photo by Thought Catalog on Unsplash

注册一个公司

不管规模多大,公司是必不可少的。自然人能够开发的东西是单机工具类产品。假如想整合更多的资源,需要一个法人身份,开公司是唯一的选择。

多途径输出

总结的形式可以是笔记、可以是视频,多途径输出自己的经验,帮助更多的人。

减少一切非必要成本

这里非必要成本包括公司财务的开支,服务器的开支,在项目初期尽可能减到最低配置。保持无负担低成本启动,可以让你不用那么焦虑,保持清醒的头脑聚焦到关键的核心产品上。

从上至下规划产品

从上至下规划产品,不要陷入技术细节。要知道,除了核心功能,其他大部分的功能都是可以通过技术手段实现。产品的方向是最重要的。其中首要的是要明确市场。通过量化使用者的数量,乘以每个用户可以给你带来的效益,得出整体的规模。然后看目前的市场情况,看从中能分到多大的蛋糕。

继续阅读独立开发的阶段性体会

React 状态机使用感受

Photo by erik cid on Unsplash

上手 react antd 之后,按照官方推荐的套娃框架 umi 和 antd pro 配合搭建了目前的项目。其中 umi 又可以使用 dva 状态管理框架进行数据流管理。

一开始我的认为是这个东西比较麻烦使用起来不太顺手,并且解决不了什么问题。但是现实是在我的项目里有很多组件共用的数据,不用状态管理会让代码显得非常冗余。学习了 dva 之后发现套娃框架非常适合上手,也精简了不少代码。

状态管理的核心是拆分状态。一开始我综合了知乎的一些回答,认为若组件之间有大量的共享数据,那么就可以使用状态机管理数据可以精简非常多的代码。

哦又是this——浅谈 React 事件绑定

Photo by Jeremy Zero on Unsplash

在使用 React JSX 事件绑定中有个最大的问题是它不会帮你处理 this 的指向问题。我刚刚上手的时候有些疑惑,看了教程之后豁然开朗。

React 事件绑定的需要和显示的修改对应事件处理函数的 this 的值。这主要是因为 Babel 开启了严格模式。若这个函数 this 指向没有改变,直接赋值给 onClick,那么函数体内的 this 仍是 undefined 。为此需要使用 bind 函数来修改函数体内的 this 指向。比如下面这段代码 :

import React, { Component } from "react";

class test extends Component {
  test() {}
  render() {
    return <div onClick="this.test.bind(this)"></div>;
  }
}

export default test;

对于一个类组件,this 指向的是类的实例,this.test 方法会沿着原型链找到类中定义的 test 方法,然后将这个类方法中的 this 替换为当前实例对象。这样一来, test 方法中的 this 就可以当前实例对象的值。

另一种方法是将 test 写出箭头函数的形式。这里有两个含义。首先 test = func 的形式,test 就是一个实例属性,但是这样仍然没有改变这个直接调用时函数内部的 this 的指向。但是假如写成箭头函数的形式,箭头函数中的 this 会使用实例对象的 this,如下所示。

import React, { Component } from "react";

class test extends Component {
  test = () => {};
  render() {
    return <div onClick="this.test.bind(this)"></div>;
  }
}

export default test;

对应视频教程

bind https://www.bilibili.com/video/BV1wy4y1D7JT?p=16

箭头函数 https://www.bilibili.com/video/BV1wy4y1D7JT?p=18

模块化工程杂感

Photo by Michael Scherback on Unsplash

为了更好的分解大规模的代码,包(package)的概念就产生了。包可以隔离命名空间,消除函数变量的命名冲突。一般的做法是,相同包下的文件都会放在在一个文件夹下。针对这个习惯,Python 在文件夹下定义__init__的方法来组织下面的小文件,JavaScript 的模块系统基本也是这个思路。

和这两者不同, Golang 不在单独在文件夹下指定一个导出文件,而是直接使用关键字 package 来指定,同时摒弃了文件导入这个概念,包为导入的最小单位。这样一来,同一个包内的各个文件可以直接使用而无需再次引入。而包外部的代码想要使用包内代码必须是显示的调用。这和它们家 Angular 的模块是一个思路。而导出文件的作用被大小写导出的内容所取代。

Windows Server 设定 eggjs 自启

Windows Server 总是感觉很心虚,有些程序相性不太好,一旦八字不合就要调试半天,若非单位有这使用 Windows Server 的传统,我是绝不用它作为主力系统。这不,今天又碰到一个 eggjs 写的转接口应用需要在 Windows Server 2012 做自启,不出所料又折腾半天。

半天时间,我试了很多种方案,比如 pm2-windows-startup,任务计划+node-cmd,无一例外失败了。其中只有 pm2-windows-service 竟然在折腾之下意外成功,这里记录一下关键点。

继续阅读Windows Server 设定 eggjs 自启

走火入魔做产品

在业余时间一直开发一款小程序应用,陆陆续续也有大半年的时间。半年时间来,我的感受是产品和开发不同,开发侧重与实现与做到,产品注重是做好。

做好相对于做到没有一个明确的目标,因此需要反复迭代。半年以来设计了很多 UX/UI,过了一段时间觉得很不好用,又推翻重来。这种自虐的感觉真的很难受。

UX/UI 到组件封装复用其实每个过程都是渐进迭代,过程很曲折,但是想到也算慢慢接近目标,也就宽慰了。放上目前的阶段性成果留作纪念。

继续阅读走火入魔做产品