日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

还在封装 xxxForm,xxxTable 残害你的同事?试试这个工具

發布時間:2024/1/11 windows 43 coder
生活随笔 收集整理的這篇文章主要介紹了 还在封装 xxxForm,xxxTable 残害你的同事?试试这个工具 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

之前寫過一篇文章 我理想中的低代碼開發工具的形態,已經吐槽了各種封裝 xxxForm,xxxTable 的行為,這里就不啰嗦了。今天再來看看我的工具達到了什么程度。

多圖預警。。。

以管理后臺一個列表頁為例

選擇對應的模板

截圖查詢區域,使用 OCR 初始化查詢表單的配置

截圖表頭,使用 OCR 初始化 table 的配置

使用 ChatGPT 翻譯中文字段

生成代碼

效果

目前我們沒有寫一行代碼,就已經達到了如下的效果

下面是一部分生成的代碼

import { reactive, ref } from 'vue'

import { IFetchTableListResult } from './api'

interface ITableListItem {
  /**
   * 決算單狀態
   */
  settlementStatus: string
  /**
   * 主合同編號
   */
  mainContractNumber: string
  /**
   * 客戶名稱
   */
  customerName: string
  /**
   * 客戶手機號
   */
  customerPhone: string
  /**
   * 房屋地址
   */
  houseAddress: string
  /**
   * 工程管理
   */
  projectManagement: string
  /**
   * 接口返回的數據,新增字段不需要改 ITableListItem 直接從這里取
   */
  apiResult: IFetchTableListResult['result']['records'][0]
}

interface IFormData {
  /**
   * 決算單狀態
   */
  settlementStatus?: string
  /**
   * 主合同編號
   */
  mainContractNumber?: string
  /**
   * 客戶名稱
   */
  customerName?: string
  /**
   * 客戶手機號
   */
  customerPhone?: string
  /**
   * 工程管理
   */
  projectManagement?: string
}

interface IOptionItem {
  label: string
  value: string
}

interface IOptions {
  settlementStatus: IOptionItem[]
}

const defaultOptions: IOptions = {
  settlementStatus: [],
}

export const defaultFormData: IFormData = {
  settlementStatus: undefined,
  mainContractNumber: undefined,
  customerName: undefined,
  customerPhone: undefined,
  projectManagement: undefined,
}

export const useModel = () => {
  const filterForm = reactive<IFormData>({ ...defaultFormData })

  const options = reactive<IOptions>({ ...defaultOptions })

  const tableList = ref<(ITableListItem & { _?: unknown })[]>([])

  const pagination = reactive<{
    page: number
    pageSize: number
    total: number
  }>({
    page: 1,
    pageSize: 10,
    total: 0,
  })

  const loading = reactive<{ list: boolean }>({
    list: false,
  })

  return {
    filterForm,
    options,
    tableList,
    pagination,
    loading,
  }
}

export type Model = ReturnType<typeof useModel>

這就是用模板生成的好處,有規范,隨時可以改,而封裝 xxxForm,xxxTable 就是一個黑盒。

原理

下面大致說一下原理

首先是寫好一個個模版,vscode 插件讀取指定目錄下模版顯示到界面上

每個模版下可能包含如下內容:

選擇模版后,進入動態表單配置界面

動態表單是讀取 config/schema.json 里的內容進行動態渲染的,目前支持 amis、form-render、formily

配置表單是為了生成 JSON 數據,然后根據 JSON 數據生成代碼。所以最終還是無法避免的使用私有的 DSL ,但是生成后的代碼是沒有私有 DSL 的痕跡的。生成代碼本質是 JSON + EJS 模版引擎編譯 src 目錄下的 ejs 文件。

為了加快表單的配置,可以自定義腳本進行操作

這部分內容是讀取 config/preview.json 內容進行顯示的

選擇對應的腳本方法后,插件會動態加載 script/index.js 腳本,并執行里面對應的方法

以 initColumnsFromImage 方法為例,這個方法是讀取剪貼板里的圖片,然后使用百度 OCR 解析出文本,再使用文本初始化表單

initColumnsFromImage: async (lowcodeContext) => {
    context.lowcodeContext = lowcodeContext;
    const res = await main.handleInitColumnsFromImage();
    return res;
  },
export async function handleInitColumnsFromImage() {
  const { lowcodeContext } = context;
  if (!lowcodeContext?.clipboardImage) {
    window.showInformationMessage('剪貼板里沒有截圖');
    return lowcodeContext?.model;
  }
  const ocrRes = await generalBasic({ image: lowcodeContext!.clipboardImage! });
  env.clipboard.writeText(ocrRes.words_result.map((s) => s.words).join('\r\n'));
  window.showInformationMessage('內容已經復制到剪貼板');
  const columns = ocrRes.words_result.map((s) => ({
    slot: false,
    title: s.words,
    dataIndex: s.words,
    key: s.words,
  }));
  return { ...lowcodeContext.model, columns };
}

反正就是可以根據自己的需求定義各種各樣的腳本。比如使用 ChatGPT 翻譯 JSON 里的指定字段,可以看我的上一篇文章 TypeChat、JSONSchemaChat實戰 - 讓ChatGPT更聽你的話

再比如要實現把中文翻譯成英文,然后英文使用駝峰語法,這樣就可以將中文轉成英文代碼變量,下面是實現的效果

選擇對應的命令菜單后 vscode 插件會加載對應模版里的腳本,然后執行里面的 onSelect 方法。

main.ts 代碼如下

import { env, window, Range } from 'vscode';
import { context } from './context';

export async function bootstrap() {
  const clipboardText = await env.clipboard.readText();
  const { selection, document } = window.activeTextEditor!;
  const selectText = document.getText(selection).trim();
  let content = await context.lowcodeContext!.createChatCompletion({
    messages: [
      {
        role: 'system',
        content: `你是一個翻譯家,你的目標是把中文翻譯成英文單詞,請翻譯時使用駝峰格式,小寫字母開頭,不要帶翻譯腔,而是要翻譯得自然、流暢和地道,使用優美和高雅的表達方式。請翻譯下面用戶輸入的內容`,
      },
      {
        role: 'user',
        content: selectText || clipboardText,
      },
    ],
  });
  content = content.charAt(0).toLowerCase() + content.slice(1);
  window.activeTextEditor?.edit((editBuilder) => {
    if (window.activeTextEditor?.selection.isEmpty) {
      editBuilder.insert(window.activeTextEditor.selection.start, content);
    } else {
      editBuilder.replace(
        new Range(
          window.activeTextEditor!.selection.start,
          window.activeTextEditor!.selection.end,
        ),
        content,
      );
    }
  });
}

使用了 ChatGPT。

再來看看,之前生成管理后臺 CURD 頁面的時候,連 mock 也一起生成了,主要邏輯放在了 complete 方法里,這是插件的一個生命周期函數。

因為 mock 服務在另一個項目里,所以需要跨目錄去生成代碼,這里我在 mock 服務里加了個接口返回 mock 項目所在的目錄

.get(`/mockProjectPath`, async (ctx, next) => {
    ctx.body = {
      status: 200,
      msg: '',
      result: __dirname,
    };
  })

生成代碼的時候請求這個接口,就知道往哪個目錄生成代碼了

const mockProjectPathRes = await axios
      .get('http://localhost:3001/mockProjectPath', { timeout: 1000 })
      .catch(() => {
        window.showInformationMessage(
          '獲取 mock 項目路徑失敗,跳過更新 mock 服務',
        );
      });
    if (mockProjectPathRes?.data.result) {
      const projectName = workspace.rootPath
        ?.replace(/\\/g, '/')
        .split('/')
        .pop();
      const mockRouteFile = path.join(
        mockProjectPathRes.data.result,
        `${projectName}.js`,
      );
      let mockFileContent = `
			import KoaRouter from 'koa-router';
			import proxy from '../middleware/Proxy';
			import { delay } from '../lib/util';

			const Mock = require('mockjs');

			const { Random } = Mock;

			const router = new KoaRouter();
			router{{mockScript}}
			module.exports = router;
			`;

      if (fs.existsSync(mockRouteFile)) {
        mockFileContent = fs.readFileSync(mockRouteFile).toString().toString();
        const index = mockFileContent.lastIndexOf(')') + 1;
        mockFileContent = `${mockFileContent.substring(
          0,
          index,
        )}{{mockScript}}\n${mockFileContent.substring(index)}`;
      }
      mockFileContent = mockFileContent.replace(/{{mockScript}}/g, mockScript);
      fs.writeFileSync(mockRouteFile, mockFileContent);
      try {
        execa.sync('node', [
          path.join(
            mockProjectPathRes.data.result
              .replace(/\\/g, '/')
              .replace('/src/routes', ''),
            '/node_modules/eslint/bin/eslint.js',
          ),
          mockRouteFile,
          '--resolve-plugins-relative-to',
          mockProjectPathRes.data.result
            .replace(/\\/g, '/')
            .replace('/src/routes', ''),
          '--fix',
        ]);
      } catch (err) {
        console.log(err);
      }

mock 項目也可以通過 vscode 插件快速創建和使用

插件源碼 https://github.com/lowcoding/lowcode-vscode

上面展示的模版都放在了 https://github.com/lowcode-scaffold/lowcode-materials 倉庫里,照著 README 步驟做就可以使用了。

總結

以上是生活随笔為你收集整理的还在封装 xxxForm,xxxTable 残害你的同事?试试这个工具的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。