应用开发平台集成表单设计器系列之3——整体集成思路及表单设计器功能深度了解

news2024/11/15 8:32:49

背景

平台需要实现自定义表单功能,作为低代码开发的一部分,通过技术预研和技术选型,选择form-create和form-create-designer这两个组件进行集成作为实现方案。通过深入了解和技术验证,确认了组件的功能能满足需求,具备良好的开放性和扩展性。
接下来,重点来说说整体设计。

核心问题

实际有个核心的问题需要先考虑清楚,即现有的开发平台低代码配置功能与表单设计器,二者的关系是什么样。思考后总结,主要有三种模式:
1.相互独立,分别用于不同的场景;
2.协作关系,现有配置功能进行初步配置,表单设计器在其基础上再进行二次调整;
3.替代关系,只保留其中一种实现方式,放弃另外一种。

开发平台现有配置功能,是通过配置+模板化技术,实现了自动生成前端页面的功能,目前只支持表单属性单列纵向展示,其实扩展为可设置两列展示实际也比较简单,合并单元格方面则略麻烦,虽然不如表单设计器直观,可以灵活的通过拖动来改变位置和次序以及预览效果,但优点是配置简便易行,通过实体属性和配置可以快速生成标准页面。
对于属性较少的实体,如系统基础数据的管理、配置数据的维护,采用标准化的模板模式来生成,配置简便,快速高效。
但不得不说,对于非标准化的复杂表单,如三五十个字段的单表,需要分组显示;主子关系表,需要多tab页展示……在这些场景下,表单的可视化配置仍然很有价值,相比原生开发,或者基于平台现有的模板式生成后手工修改,仍存在大幅提高开发效率的空间。

基于上述考虑,模式3只保留其中实现方式首先出局;模式1会形成一定程度的功能割裂,某个功能实现时即需要评估应该用哪种模式来实现,如随着业务发展和需求变动,需要调整实现模式时,意味着原模式的配置需要重来一遍。模式2的协作模式相对而言是最佳方案,对于简单的实体,直接通过配置化功能快速实现,对于复杂的实体,系统根据实体配置自动生成一个两列的表单,填充到表单设计器上,从而进行二次修改与调整。

整体集成思路

开发阶段,集成form-create-designer,实现表单的可视化配置。
运行阶段,集成form-create,实现表单的运行。

表单设计器技术预研

组件列表配置

官方说明

这里说的组件列表是指表单设计器左侧的分组及组件,如下图红框所示:
image.png
官方说明文档章节中命名是左侧按钮,api部分命名使用的是menuItem,分组使用menu,并不一致,所以我重新命名为组件列表,与业务含义更贴合。

示例中文档错误的地方较多,比如
追加自定义拖拽组件(http://designer.form-create.com/guide/menu.html#%E7%A4%BA%E4%BE%8B)

<template>
  <fc-designer ref="designer"/>
</template>

<script>
export default {
    name: 'app',
    data() {
      return {};
    },
    created(){
      this.$refs.designer.appendMenuItem({
        icon: 'icon-checkbox',
        name: 'checkbox',
        label: '单选框'
      });
    }
};
</script>

这里加组件,但是明显没有指定分组……应该是有问题的,然后去别处找答案,在appendMenuItem的方法说明中,实际有两个参数,第一个参数是分组名,第二个参数才是组件。

type appendMenuItem = (menuName:string, item: MenuItem) => void

基于上述现状,通过摸索来说说集成方面的具体实现。

分组配置

官方内置了三个分组:main,aide,layout,每个分组下预置了若干组件。
前面提到过,开发平台这边实际有大量自封装的组件,比如数据字典下拉,组织机构选择、人员选择等,放到官方现有分组中并不合适,需要添加自己的分组单独显示更好一些。
官方提供了Api,addMenu = (menu: Menu) => void,参数的数据结构如下:

//左侧拖拽按钮分类
export interface Menu {
    title: string;
    name: string;
    list: MenuItem[]
}

该方法虽然可用,但是没提供插入方法,比如,我想把自定义分组放到最上面,明显做不到。
经摸索后,采用如下方式:
给组件指定menu属性

<fc-designer ref="designer" :menu="menu"/>

通过设置menu变量来重置设置分组。

menu: [
        {
          title: '自定义',
          name: 'custom',
          list: []
        }
]

其中分组要遵循menu对象的数据结构,即留一个空的数组属性list,然后在mouted事件中注册组件,并将组件添加到分组的list数组中

mounted() {
    //注册组件
    this.$refs.designer.addComponent(DictionarySelectDesigner)
  	//声明组件
    const dictionarySelect = {
      icon: DictionarySelectDesigner.icon,
      name: DictionarySelectDesigner.name,
      label: DictionarySelectDesigner.label
    }
    //
    this.menu[0].list.push(dictionarySelect)
}

实现效果如下:
image.png
如要保留官方的分组,则可以参考官方初始化的方式,把分组和组件按需加进来,并可以灵活选择去除认为不适用的部分组件。

以下是把fcd自带的布局组件分组(layout)以及下属的栅格布局(row)加入进来。

menu: [
        {
          title: '自定义',
          name: 'custom',
          list: []
        },
        {
          name: 'layout',
          title: '布局组件',
          list: [row]
        }
      ]

显示效果如下:
image.png
注意,上面操作栅格布局组件实际并没有正常显示名称,拖放时也会报错,无法正常使用……。

组件属性

作为一个独立的组件,位于表单设计器左侧列表中,首先需要有三要素:组件标签(label)、组件名称(name)、组件图标(icon)。实际对应的数据结构如下:

export interface MenuItem {
    label: string,
    name: string,
    icon: string;
}

注意,这里的name实际是对应着自定义组件的编码,这层对应关系是隐含的,官方文档并未着重说明。

组件配置

上面介绍了分组如何配置,下面来说下分组中的具体组件如何配置。
首先来说下,如何配置使用fcd自身的组件,官方文档中说的过于简略,可以参照官方源码中来配置。

import radio from './rule/radio';
import checkbox from './rule/checkbox';
import input from './rule/input';
import number from './rule/number';
import select from './rule/select';
import _switch from './rule/switch';
import slider from './rule/slider';
import time from './rule/time';
import date from './rule/date';
import rate from './rule/rate';
import color from './rule/color';
import row from './rule/row';
import divider from './rule/divider';
import cascader from './rule/cascader';
import upload from './rule/upload';
import transfer from './rule/transfer';
import tree from './rule/tree';
import alert from './rule/alert';
import span from './rule/span';
import space from './rule/space';
import button from './rule/button';
import editor from './rule/editor';
import tab from './rule/tab';

export default function createMenu() {
    return [
        {
            name: 'main',
            title: '表单组件',
            list: [
                input, number, radio, checkbox, select, _switch, time, date, slider, rate, color, cascader, upload, transfer, tree, editor
            ]
        },
        {
            name: 'aide',
            title: '辅助组件',
            list: [
                alert, button, span, divider
            ]
        },
        {
            name: 'layout',
            title: '布局组件',
            list: [
                row, /*tab,*/ space
            ]
        },
    ];
}

fcd的源码中是使用的相对路径,我们实际安装配置fcd组件,会放到npm_modules目录下,引用的时候不能使用如下方式:

import row from '@form-create/designer/src/config/rule/row.js'

更换为下面这种方式

import row from '@form-create/designer'

引用阶段不报错了,但是组件名称没有正常显示,拖放时也会报错。

综上,目前没找到了灵活配置内置组件的方式,建议要么全部保留,要么全部移除。

临时方案

保留fcd内置组件,通过API将自定义分组和组件添加进去。

<template>
  <fc-designer v-model="value" ref="designer" />
</template>

<script lang="ts">
import DictionarySelectDesigner from '@/components/abc/FormCreateComponent/DictionarySelect.js'

export default {
  components: { DictionarySelectDesigner },
  data() {
    return {
      //表单数据
      value: {},
      //组件参数配置
      option: {
        //表单提交事件
        onSubmit: function (formData) {
          alert(JSON.stringify(formData))
        }
      }
    }
  },
  created() {},
  mounted() {
    //插入组件规则
    this.$refs.designer.addComponent(DictionarySelectDesigner)

    //读取自定义组件信息,生成左侧组件对象
    const dictionarySelect = {
      icon: DictionarySelectDesigner.icon,
      name: DictionarySelectDesigner.name,
      label: DictionarySelectDesigner.label
    }
    // //插入自定义分组及自定义组件
    this.$refs.designer.addMenu({
      title: '自定义',
      name: 'custom',
      list: [dictionarySelect]
    })    
  },
  methods: {}
}
</script>

<style></style>

自定义组件实现

解决了组件列表配置问题,接下来是自定义组件封装问题,在上一篇技术验证中,实际拿数据字典下拉组件作为示例已经做过说明,不过相对零散,本节完整说下。

官方说明

自定义组件需要遵循fcd的规范和要求,官方说明地址为http://designer.form-create.com/guide/component.html#%E5%AD%97%E6%AE%B5%E8%AF%B4%E6%98%8E

字段名说明类型
name组件名称string
rule获取组件生成规则的方法Function
props获取组件配置规则的方法Function
children子组件名称string
drag是否可以拖入组件string | Boolean
dragBtn是否显示拖拽按钮Boolean

首先,组件名称name非常重要,唯一性标识该组件,将该组件添加到fcd左侧组件列表时,实际使用的就是属性,需要一致起来才能实现对应关系。
其次,rule是一个方法,当组件被拖放到表单区域时,由该方法决定如何来生成UI元素,以内置checkbox组件为例

rule() {
  //如果在 props 方法中需要修改 rule 的属性,需要提前在 rule 上定义对应的属性
  return {
    //生成组件的名称
    type: name,
    //field 自定不能重复,所以这里每次都会生成一个新的
    field: uniqueId(),
    title: label,
    info: '',
    effect: {
      fetch: ''
    },
    //这里设置组件的默认props配置项, 在下面的 props 方法里面设置无效
    props: {},
    options: [
      {value: '1', label: '选项1'},
      {value: '2', label: '选项2'},
    ]
  };
}

再次,props也是一个方法,用于生成组件的配置属性

props() {
  return [
    //生成`checkbox`组件的`options`配置规则
    FcDesigner.makeOptionsRule('options'),
    {
      type: 'switch',
      field: 'type',
      title: '按钮类型',
      props: {activeValue: 'button', inactiveValue: 'default'}
    }, 
    {type: 'switch', field: 'disabled', title: '是否禁用'}, 
    {
      type: 'inputNumber',
      field: 'min',
      title: '可被勾选的 checkbox 的最小数量'
    }, 
    {type: 'inputNumber', field: 'max', title: '可被勾选的 checkbox 的最大数量'}, 
    {
      type: 'input',
      field: 'textColor',
      title: '按钮形式的 Checkbox 激活时的文本颜色'
    }, 
    {type: 'input', field: 'fill', title: '按钮形式的 Checkbox 激活时的填充色和边框色'}]
}

image.png

数据字典下拉组件

开发平台研发过程中封装了一个基于系统数据字典的下拉组件,其实现的功能是通过通过字典类型编码,自动请求后端服务,拿到字典项后填充下拉列表,源码如下:

<template>
  <el-select
    v-model="selectedValue"
    :size="size"
    clearable
    :multiple="multiple"
    :disabled="readonly"
    style="width: 100%; margin: 0 auto"
    @change="change"
  >
    <el-option
      v-for="item in dictionaryItemList"
      :key="item.code"
      :value="item.code"
      :label="item.label"
    />
  </el-select>
</template>

<script>
export default {
  props: {
    modelValue: {
      type: [String, Array],
      required: false,
      default: ''
    },
    code: {
      type: String,
      default: ''
    },
    readonly: {
      type: Boolean,
      required: false,
      default: false
    },
    size: {
      type: String,
      default: ''
    },
    multiple: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      dictionaryItemList: [],
      selectedValue: []
    }
  },
  watch: {
    code: {
      immediate: true,
      handler: 'loadData'
    },
    modelValue: {
      immediate: true,
      handler: 'setSelected'
    }
  },
  methods: {
    change(value) {
      if (!this.multiple) {
        let name = ''
        this.dictionaryItemList.forEach((item) => {
          if (item.code === value) {
            name = item.label
            return
          }
        })
        // 更新绑定值
        this.$emit('update:modelValue', value)
        // 注意,此处若命令为change,则可能会与底层实现冲突,导致执行两次
        this.$emit('my-change', value, name)
      } else {
        // 更新绑定值
        this.$emit('update:modelValue', value)
      }
    },
    setSelected() {
      if (this.modelValue != '') {
        if (this.multiple) {
          if (Array.isArray(this.modelValue)) {
            this.selectedValue = this.modelValue
          } else {
            this.selectedValue.push(this.modelValue)
          }
        } else {
          this.selectedValue = this.modelValue
        }
      } else {
        if (this.multiple) {
          this.selectedValue = []
        } else {
          this.selectedValue = ''
        }
      }
    },
    loadData() {
      if (this.code) {
        this.dictionaryItemList = []
        this.$api.system.dictionaryType.getItem(this.code).then((res) => {
          this.dictionaryItemList = res.data
        })
      }
    }
  }
}
</script>

该功能的详细设计与实现可参见之前的博文:https://blog.csdn.net/seawaving/article/details/128225379

二次封装

之所以要二次封装,是因为自定义组件需要遵循fcd的规范和要求,才能融入到fcd中,拖放时正常显示以及设置属性。
封装其实不难,引入原组件,按照fcd组件要求定义相关属性,完整源码如下:

import FcDesigner from '@form-create/designer'
import { markRaw } from 'vue'
import DictionarySelect from '@/components/abc/DictionarySelect/DictionarySelect.vue'
const label = '下拉列表'
const name = 'DictionarySelect'
let i = 1
const uniqueId = () => `uni${i++}`
export default {
  icon: 'icon-select',
  label,
  name,
  rule() {
    return {
      type: name,
      component: markRaw(DictionarySelect),
      field: uniqueId(),
      title: label,
      info: '',
      props: {}
    }
  },
  props() {
    return [
      //生成`checkbox`组件的`options`配置规则
      // FcDesigner.makeOptionsRule('options'),
      { type: 'input', field: 'code', title: '字典类型编码' }
    ]
  }
}

其中的注意事项还是要说一下。
首先,标签(label)和图标(icon)并非fcd自定义组件的必须实现项,在组件内部定义和设置,主要是考虑了将来添加到左侧组件列表时的便利,即可以采用如下方式:

 //读取自定义组件信息,生成左侧组件对象
    const dictionarySelect = {
      icon: DictionarySelectDesigner.icon,
      name: DictionarySelectDesigner.name,
      label: DictionarySelectDesigner.label
    }

其次,需要注意rule规则中的field属性,需要保持唯一,因为同一个组件会被多次拖入到表单中重复使用,标识需要唯一,此处暂时使用了一个方法来,以后会设置为实体的属性编码。
最后,引入了markRaw来处理,如不加,浏览器会报警告,大概意思是组件自身已经是响应式的,不需要再包一层。

还有一点,是在props中指定了该组件的配置属性,这里用一个文本框来设置字典类型编码,先做简单化处理,后续实际改造成为弹出对话框,从系统字典中搜索和选择更便利。

自定义操作按钮

官方说明

官方说明极简,通过名为handle的插槽可添加自定义按钮,示例代码如下

<template>
  <fc-designer ref="designer">
    <template slot="handle">
      <ElButton>自定义按钮</ElButton>
    </template>
  </fc-designer>
</template>

<script>
export default {
    name: 'app',
    data() {
      return {};
    }
};
</script>

实测效果如下:
image.png
预览和清空按钮是fcd内置的,最左侧“自定义按钮”是我们自己加的。

实战

官方提供了扩展能力,在实际应用中能发挥什么作用呢?
我们可以添加自定义按钮,然后调用fcd的API,来实现一些额外的功能,如通过导入json的方式来生成表单。
也就是说,可以把下图中官方示例中的功能按钮,放到该区域来实现。
image.png

表单API

这里设计两个概念,一是表单的配置,即表单的属性设置信息,如下图所示
image.png
二是通过表单设计器,拖拽组件并配置属性后,fcd会生成对应的json数据,这部分json官方命名为规则(rule),从字面意思上不太直观,不好理解。

这里涉及到FCD组件的4个API,分别是读取属性、读取规则和设置属性、设置规则

<template>
  <fc-designer ref="designer" :menu="menu"/>
</template>

<script>
export default {
  name: 'app',
  data() {
    return {};
  },
  methods:{
    getForm(){
      //FcDesigner 生成的`JSON`
      const FcDesignerRule = this.$refs.designer.getRule();
      //FcDesigner 生成的`options`
      const FcDesignerOptions = this.$refs.designer.getOption();
    }
  }
};
</script>

通过设置规则和属性,来回显表单

<template>
  <fc-designer ref="designer"/>
</template>

<script>
export default {
  name: 'app',
  data() {
    return {};
  },
  created(){
    this.$refs.designer.setRule(FcDesignerRule);
    this.$refs.designer.setOption(FcDesignerOption);
  }
};
</script>

接下来,表单设计器的最终目的是生成表单,是通过表单设计器来获取属性和规则,赋值给fc组件

<template>
  <form-create
      v-model="fapi"
      :rule="rule"
      :option="option"
      @submit="onSubmit"
  ></form-create>
</template>

<script>
import formCreate from "@form-create/element-ui";

//FcDesigner 生成的`JSON`
const FcDesignerRule = '[{"type":"input","field":"cuk5qqdw3umc","title":"输入框","info":"","_fc_drag_tag":"input","hidden":false,"display":true}]';

//FcDesigner 生成的`options`
const FcDesignerOptions = '{"form":{"labelPosition":"right","size":"mini","labelWidth":"125px","hideRequiredAsterisk":false,"showMessage":true,"inlineMessage":false}}';

export default {
  data () {
    return {
      fapi: null,
      rule: formCreate.parseJson(FcDesignerRule),
      option: formCreate.parseJson(FcDesignerOptions)
    }
  },
  methods: {
    onSubmit (formData) {
      //todo 提交表单
    }
  }
}
</script>

开发平台资料

平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:csdn专栏
开源地址:Gitee
开源协议:MIT
开源不易,欢迎收藏、点赞、评论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1228761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

移动机器人路径规划(二)--- 图搜索基础,Dijkstra,A*,JPS

目录 1 图搜索基础 1.1 机器人规划的配置空间 Configuration Space 1.2 图搜索算法的基本概念 1.3 启发式的搜索算法 Heuristic search 2 A* Dijkstra算法 2.1 Dijkstra算法 2.2 A*&&Weighted A*算法 2.3 A* 算法的工程实践中的应用 3 JPS 1 图搜索基础 1.1…

V100 GPU服务器安装GPU驱动教程

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

计算机网络——物理层-信道的极限容量(奈奎斯特公式、香农公式)

目录 介绍 奈氏准则 香农公式 介绍 信号在传输过程中&#xff0c;会受到各种因素的影响。 如图所示&#xff0c;这是一个数字信号。 当它通过实际的信道后&#xff0c;波形会产生失真&#xff1b;当失真不严重时&#xff0c;在输出端还可根据已失真的波形还原出发送的码元…

JVM垃圾回收相关概念

目录 一、System.gc()的理解 二、内存溢出与内存泄露 &#xff08;一&#xff09;OOM &#xff08;二&#xff09;内存泄露 三、StopTheWorld 四、垃圾回收的并行与并发 五、安全点与安全区域 &#xff08;一&#xff09;安全点 &#xff08;二&#xff09;安全区域 …

数据结构【DS】树与二叉树的应用

哈夫曼树 树的带权路径长度最小的二叉树WPL 路径长度【边数】 * 结点权值n个叶结点的哈夫曼树共有 2n-1 个结点 哈夫曼树的任意非叶结点的左右子树交换后仍是哈夫曼树对同一组权值&#xff0c;可能存在不同构的多棵哈夫曼树&#xff0c;但树的带权路径长度最小且唯一哈夫曼树…

C/C++高精度

个人主页&#xff1a;仍有未知等待探索_C语言疑难,数据结构,小项目-CSDN博客 专题分栏&#xff1a;算法_仍有未知等待探索的博客-CSDN博客 为什么需要高精度算法&#xff1f; 由于c不能进行位数过高的数据运算&#xff0c;所以要通过模拟数组来进行运算&#xff0c;首先是加法。…

基于类电磁机制算法优化概率神经网络PNN的分类预测 - 附代码

基于类电磁机制算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于类电磁机制算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于类电磁机制优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针…

使用ChatGPT进行数据分析案例——贷款数据分析

目录 数据数据 每一行是一个记录,代表着一笔贷款,每一列是一个特征,一共1万多条数据,最后一列非常重要save_loans是否成功收回

SpringBean的配置详解 --中

目录 Bean的初始化和销毁方法配置 Bean的初始化和销毁方法配置 扩展 Bean的实例化 Bean的初始化和销毁方法配置 当lazy-init设置为true时为延迟加载&#xff0c;也就是当Spring容器加载的时候&#xff0c;不会立即创建Bean实例&#xff0c;等待用到时再创建Bean实例并存储到单…

[AutoSar]CP autosar 面试题

目录 关键词前言面试官提问答案 关键词 嵌入式、C语言、autosar、面试题 前言 以前面试中的一些常提到的问题&#xff0c;在这里整理一下&#xff0c;希望对要去面试的道友有所帮助。 其中问题的答案后续有时间会再更新整理。 面试官提问 1.Autosar 概述&#xff1a; 解释 …

传输层协议-TCP协议

目录 TCP协议格式理解可靠性序号与确认序号16位窗口大小六个标志位连接管理机制三次握手四次挥手 确认应答机制&#xff08;ACK&#xff09;超时空重传机制流量控制滑动窗口拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结基于TCP应用层协议TCP/UDP对比用UDP实现…

AD教程 (十九)PCB板框的评估和层叠设置

AD教程 &#xff08;十九&#xff09;PCB板框的评估和层叠设置 板子越小&#xff0c;层数越少&#xff0c;成本越低 PCB板框评估 器件摆放 CtrlA 选中全部器件点击工具&#xff0c;选择器件摆放&#xff0c;选择在矩形区域排列 框定矩形区域&#xff0c;器件就会摆放在框定的矩…

416. 分割等和子集问题(动态规划)

题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…

[AutoSar]工程中的cpuload陷阱(三)测试

目录 关键词平台说明背景一、 测试结果对比1.1 不带cache1.2 带cache 二、小结 关键词 嵌入式、C语言、autosar 平台说明 项目ValueOSautosar OSautosar厂商vector芯片厂商TI编程语言C&#xff0c;C编译器HighTec (GCC) 背景 接着工程中的cpuload陷阱&#xff08;二)中的描述…

Android Spider App逆向 Frida - 夜神模拟器安装配置 基本使用

文章目录 前言一、Frida简单介绍&#xff1f;1.Frida是什么2.Frida原理(建议了解一下&#xff0c;否则后续的安装会有些懵懂) 二、Frida下载1.pip安装frida模块2.查看本地的frida版本&#xff0c;需要与模拟器端/手机端的版本对应&#xff0c;否则会出错3.frida下载 三、Frida安…

Figma 插件学习(一)

一.插件介绍 插件在文件中运行&#xff0c;执行一个或多个用户操作&#xff0c;并允许用户自定义其体验或创建更高效的工作流程。 插件通过专用插件API与Figma的编辑器交互。还可以利用外部Web API。 1.插件API 插件API支持读写功能&#xff0c;允许查看、创建和修改文件的…

读像火箭科学家一样思考笔记03_第一性原理(上)

1. 思维的两种障碍 1.1. 为什么知识会成为一种缺陷而非一种美德 1.1.1. 知识是一种美德 1.1.2. 知识同样的特质也会把它变成一种缺点 1.1.3. 知识确实是个好东西&#xff0c;但知识的作用应该是给人们提供信息&#xff0c;而不是起约束作用 1.1.4. 知识应该启发智慧&#…

2024年软件测试面试必看系列,看完去面试你会感谢我的!!

朋友圈点赞的测试用例 功能测试 1点赞后是否显示结果 2.点赞后是否可以取消; 3.点赞取消后是否可以重复点赞; 4.共同好友点赞后&#xff0c;是否有消息提醒; 5.非共同好友点赞后&#xff0c;是否有消息提醒; 6.点击点赞人昵称&#xff0c;是否可以跳转到他/她的主页; 7.自己能…

NLP学习:深入NLP

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 之前学过一段时间NLP,因为其中涉及到一些深度学习常用的知识或者框架,但苦于不系统以及没有任务focus不能长久.这里借助微软的教程写点东西. tokenization&&representation 将一句话中的单词分割就是分词(…

如何看待人工智能行业发展

随着人工智能技术的飞速发展&#xff0c;这个领域的就业前景也日益广阔。人工智能在各行各业都有广泛的应用&#xff0c;包括医疗、金融、制造业、教育等。因此&#xff0c;对于想要追求高薪、高技能职业的人来说&#xff0c;学习人工智能是一个非常有前景的选择。 首先&#x…