fuchengshen
2022-06-20 9d6c67cd2105f09762e619706bcb48613f0aa2ab
build/plugins/cool.ts
@@ -10,299 +10,299 @@
// 格式化
function format(data: any) {
   return {
      label: data.label,
      prop: data.prop,
      ...data,
      component: data.component
   };
  return {
    label: data.label,
    prop: data.prop,
    ...data,
    component: data.component
  };
}
// 颜色
const colors = [
   "#409EFF",
   "#67C23A",
   "#E6A23C",
   "#F56C6C",
   "#909399",
   "#B0CFEB",
   "#FF9B91",
   "#E6A23C",
   "#BFAD6F",
   "#FB78F2"
  "#409EFF",
  "#67C23A",
  "#E6A23C",
  "#F56C6C",
  "#909399",
  "#B0CFEB",
  "#FF9B91",
  "#E6A23C",
  "#BFAD6F",
  "#FB78F2"
];
// 组件处理器
const handler = {
   // 单选
   dict({ comment }) {
      const [label, ...arr] = comment.split(" ");
  // 单选
  dict({ comment }) {
    const [label, ...arr] = comment.split(" ");
      // 选择列表
      const list = arr.map((e: string, i: number) => {
         const [value, label] = e.split("-");
         const d: any = {
            label,
            value: isNaN(Number(value)) ? value : Number(value)
         };
    // 选择列表
    const list = arr.map((e: string, i: number) => {
      const [value, label] = e.split("-");
      const d: any = {
        label,
        value: isNaN(Number(value)) ? value : Number(value)
      };
         if (i > 0 && colors[i]) {
            d.color = colors[i];
         }
      if (i > 0 && colors[i]) {
        d.color = colors[i];
      }
         return d;
      });
      return d;
    });
      const d: any = {
         table: {
            label,
            dict: list
         },
         form: {
            label,
            component: {
               name: "",
               options: list
            }
         }
      };
    const d: any = {
      table: {
        label,
        dict: list
      },
      form: {
        label,
        component: {
          name: "",
          options: list
        }
      }
    };
      // 默认值
      if (list[0]) {
         d.form.value = list[0].value;
      }
    // 默认值
    if (list[0]) {
      d.form.value = list[0].value;
    }
      // 匹配组件
      d.form.component.name = arr.length > 4 ? "el-select" : "el-radio-group";
    // 匹配组件
    d.form.component.name = arr.length > 4 ? "el-select" : "el-radio-group";
      return d;
   },
    return d;
  },
   // 多选
   dict_multiple({ comment }) {
      const { table, form }: any = handler.dict({ comment });
  // 多选
  dict_multiple({ comment }) {
    const { table, form }: any = handler.dict({ comment });
      if (!form.component.props) {
         form.component.props = {};
      }
    if (!form.component.props) {
      form.component.props = {};
    }
      if (!form.value) {
         form.value = [];
      }
    if (!form.value) {
      form.value = [];
    }
      switch (form.component.name) {
         case "el-select":
            form.component.props.multiple = true;
            form.component.props.filterable = true;
            break;
         case "el-radio-group":
            form.component.name = "el-checkbox-group";
            break;
      }
    switch (form.component.name) {
      case "el-select":
        form.component.props.multiple = true;
        form.component.props.filterable = true;
        break;
      case "el-radio-group":
        form.component.name = "el-checkbox-group";
        break;
    }
      return {
         table,
         form
      };
   }
    return {
      table,
      form
    };
  }
};
// 解析body
function parseJson(req: any) {
   return new Promise((resolve, reject) => {
      let d = "";
      req.on("data", function (chunk: Buffer) {
         d += chunk;
      });
      req.on("end", function () {
         try {
            resolve(JSON.parse(d));
         } catch (e) {
            reject(e);
         }
      });
   });
  return new Promise((resolve, reject) => {
    let d = "";
    req.on("data", function (chunk: Buffer) {
      d += chunk;
    });
    req.on("end", function () {
      try {
        resolve(JSON.parse(d));
      } catch (e) {
        reject(e);
      }
    });
  });
}
// 创建组件
function createComponent(item: any) {
   const { propertyName: prop, comment: label } = item;
  const { propertyName: prop, comment: label } = item;
   let d = null;
  let d = null;
   rules.forEach((r: any) => {
      const s = r.test.find((e: any) => {
         if (isRegExp(e)) {
            return e.test(prop);
         }
  rules.forEach((r: any) => {
    const s = r.test.find((e: any) => {
      if (isRegExp(e)) {
        return e.test(prop);
      }
         if (isFunction(e)) {
            return e(prop);
         }
      if (isFunction(e)) {
        return e(prop);
      }
         if (isString(e)) {
            const re = new RegExp(`${e}$`);
            return re.test(prop.toLocaleLowerCase());
         }
      if (isString(e)) {
        const re = new RegExp(`${e}$`);
        return re.test(prop.toLocaleLowerCase());
      }
         return false;
      });
      return false;
    });
      if (s) {
         if (r.handler) {
            const fn = isString(r.handler) ? handler[r.handler] : r.handler;
    if (s) {
      if (r.handler) {
        const fn = isString(r.handler) ? handler[r.handler] : r.handler;
            if (isFunction(fn)) {
               d = fn(item);
            }
         } else {
            d = {
               ...r,
               test: undefined
            };
         }
      }
   });
        if (isFunction(fn)) {
          d = fn(item);
        }
      } else {
        d = {
          ...r,
          test: undefined
        };
      }
    }
  });
   function parse(v: any) {
      if (v?.name) {
         return {
            prop,
            label,
            component: v
         };
      } else {
         return {
            prop,
            label,
            ...v
         };
      }
   }
  function parse(v: any) {
    if (v?.name) {
      return {
        prop,
        label,
        component: v
      };
    } else {
      return {
        prop,
        label,
        ...v
      };
    }
  }
   return {
      column: parse(d?.table),
      item: parse(d?.form)
   };
  return {
    column: parse(d?.table),
    item: parse(d?.form)
  };
}
// 获取页面标识
function getPageName(router: string) {
   if (router.indexOf("/") === 0) {
      router = router.substr(1, router.length);
   }
  if (router.indexOf("/") === 0) {
    router = router.substr(1, router.length);
  }
   return router ? `name: "${router.replace("/", "-")}",` : "";
  return router ? `name: "${router.replace("/", "-")}",` : "";
}
// 时间合并
function datetimeMerge({ columns, item }: any) {
   if (["startTime", "startDate"].includes(item.prop)) {
      const key = item.prop.replace("start", "");
  if (["startTime", "startDate"].includes(item.prop)) {
    const key = item.prop.replace("start", "");
      if (columns.find((e: any) => e.propertyName == "end" + key)) {
         item.prop = key.toLocaleLowerCase();
         const isTime = item.prop == "time";
         item.label = isTime ? "时间范围" : "日期范围";
         item.hook = "datetimeRange";
         item.component = {
            name: "el-date-picker",
            props: {
               type: isTime ? "datetimerange" : "daterange",
               valueFormat: isTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD 00:00:00",
               defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]
            }
         };
      }
   }
    if (columns.find((e: any) => e.propertyName == "end" + key)) {
      item.prop = key.toLocaleLowerCase();
      const isTime = item.prop == "time";
      item.label = isTime ? "时间范围" : "日期范围";
      item.hook = "datetimeRange";
      item.component = {
        name: "el-date-picker",
        props: {
          type: isTime ? "datetimerange" : "daterange",
          valueFormat: isTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD 00:00:00",
          defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]
        }
      };
    }
  }
}
// 创建文件
function createVue({ router, columns, prefix, api, module, filename }: any): void {
   const upsert: any = {
      items: []
   };
  const upsert: any = {
    items: []
  };
   const table: any = {
      columns: []
   };
  const table: any = {
    columns: []
  };
   // 遍历
   columns.forEach((e: any) => {
      // 组件
      const { item, column }: any = createComponent(e);
  // 遍历
  columns.forEach((e: any) => {
    // 组件
    const { item, column }: any = createComponent(e);
      // 验证规则
      if (!e.nullable) {
         item.required = true;
      }
    // 验证规则
    if (!e.nullable) {
      item.required = true;
    }
      // 忽略部分字段
      if (!["createTime", "updateTime", "id", "endTime", "endDate"].includes(item.prop)) {
         datetimeMerge({ columns, item });
    // 忽略部分字段
    if (!["createTime", "updateTime", "id", "endTime", "endDate"].includes(item.prop)) {
      datetimeMerge({ columns, item });
         if (!item.component) {
            item.component = {
               name: "el-input"
            };
         }
      if (!item.component) {
        item.component = {
          name: "el-input"
        };
      }
         upsert.items.push(format(item));
      }
      upsert.items.push(format(item));
    }
      if (!["cl-codemirror", "cl-editor-quill"].includes(column.component?.name)) {
         table.columns.push(format(column));
      }
   });
    if (!["cl-codemirror", "cl-editor-quill"].includes(column.component?.name)) {
      table.columns.push(format(column));
    }
  });
   // 服务
   const service = prefix.replace("/admin", "service").replace(/\//g, ".");
  // 服务
  const service = prefix.replace("/admin", "service").replace(/\//g, ".");
   // 请求路径
   const paths = api.map((e: any) => e.path);
  // 请求路径
  const paths = api.map((e: any) => e.path);
   // 权限
   const permission: any = {
      add: paths.includes("/add"),
      del: paths.includes("/delete"),
      update: paths.includes("/info") && paths.includes("/update"),
      page: paths.includes("/page"),
      upsert: true
   };
   permission.upsert = permission.add || permission.update;
  // 权限
  const permission: any = {
    add: paths.includes("/add"),
    del: paths.includes("/delete"),
    update: paths.includes("/info") && paths.includes("/update"),
    page: paths.includes("/page"),
    upsert: true
  };
  permission.upsert = permission.add || permission.update;
   // 是否有操作栏
   if (permission.del || permission.upsert) {
      const d: any = {
         type: "op",
         buttons: []
      };
  // 是否有操作栏
  if (permission.del || permission.upsert) {
    const d: any = {
      type: "op",
      buttons: []
    };
      if (permission.upsert) {
         d.buttons.push("edit");
      }
    if (permission.upsert) {
      d.buttons.push("edit");
    }
      if (permission.del) {
         d.buttons.push("delete");
      }
    if (permission.del) {
      d.buttons.push("delete");
    }
      table.columns.push(d);
   }
    table.columns.push(d);
  }
   // 是否多选、序号
   if (permission.del) {
      table.columns.unshift({
         type: "selection"
      });
   } else {
      table.columns.unshift({
         label: "#",
         type: "index"
      });
   }
  // 是否多选、序号
  if (permission.del) {
    table.columns.unshift({
      type: "selection"
    });
  } else {
    table.columns.unshift({
      label: "#",
      type: "index"
    });
  }
   // 代码模板
   const temp = `<template>
  // 代码模板
  const temp = `<template>
    <cl-crud :ref="setRefs('crud')" @load="onLoad">
        <el-row type="flex" align="middle">
            <!-- 刷新按钮 -->
@@ -325,11 +325,10 @@
            <cl-pagination />
        </el-row>
        ${
         permission.update
            ? '<!-- 新增、编辑 -->\n<cl-upsert :ref="setRefs(\'upsert\')" v-bind="upsert" />'
            : ""
      }
        ${permission.update
      ? '<!-- 新增、编辑 -->\n<cl-upsert :ref="setRefs(\'upsert\')" v-bind="upsert" />'
      : ""
    }
    </cl-crud>
</template>
@@ -344,13 +343,12 @@
    setup() {
        const { refs, setRefs, service } = useCool();
        ${
         permission.upsert
            ? "// 新增、编辑配置\nconst upsert = reactive<Upsert>(" +
              JSON.stringify(upsert) +
              ");"
            : ""
      }
        ${permission.upsert
      ? "// 新增、编辑配置\nconst upsert = reactive<Upsert>(" +
      JSON.stringify(upsert) +
      ");"
      : ""
    }
        // 表格配置
        const table = reactive<Table>(${JSON.stringify(table)});
@@ -372,61 +370,61 @@
});
</script>`;
   const content = prettier.format(temp, {
      parser: "vue",
      useTabs: true,
      tabWidth: 4,
      endOfLine: "lf",
      semi: true,
      jsxBracketSameLine: true,
      singleQuote: false,
      printWidth: 100,
      trailingComma: "none"
   });
  const content = prettier.format(temp, {
    parser: "vue",
    useTabs: true,
    tabWidth: 4,
    endOfLine: "lf",
    semi: true,
    jsxBracketSameLine: true,
    singleQuote: false,
    printWidth: 100,
    trailingComma: "none"
  });
   // views 目录是否存在
   const dir = path.join(coolPath, `modules/${module}/views`);
   if (!fs.existsSync(dir)) fs.mkdirSync(dir);
  // views 目录是否存在
  const dir = path.join(coolPath, `modules/${module}/views`);
  if (!fs.existsSync(dir)) fs.mkdirSync(dir);
   // 创建文件
   fs.createWriteStream(path.join(dir, `${filename}.vue`), {
      flags: "w"
   }).write(content);
  // 创建文件
  fs.createWriteStream(path.join(dir, `${filename}.vue`), {
    flags: "w"
  }).write(content);
}
export const cool = (): Plugin | null => {
   return {
      name: "vite-cool",
      configureServer(server) {
         server.middlewares.use(async (req, res, next) => {
            function done(data) {
               res.writeHead(200, { "Content-Type": "text/html;charset=UTF-8" });
               res.end(JSON.stringify(data));
            }
  return {
    name: "vite-cool",
    configureServer(server) {
      server.middlewares.use(async (req, res, next) => {
        function done(data) {
          res.writeHead(200, { "Content-Type": "text/html;charset=UTF-8" });
          res.end(JSON.stringify(data));
        }
            if (req.url.includes("/__cool_createMenu")) {
               try {
                  const body: any = await parseJson(req);
                  await createVue(body);
                  done({
                     code: 1000
                  });
               } catch (e) {
                  done({
                     code: 1001,
                     message: e.message
                  });
               }
            } else if (req.url.includes("/__cool_modules")) {
               const dirs = fs.readdirSync(path.join(coolPath, "modules"));
               done({
                  code: 1000,
                  data: dirs.filter((e) => !e.includes("."))
               });
            } else {
               next();
            }
         });
      }
   };
        if (req.url.includes("/__cool_createMenu")) {
          try {
            const body: any = await parseJson(req);
            await createVue(body);
            done({
              code: 1000
            });
          } catch (e) {
            done({
              code: 1001,
              message: e.message
            });
          }
        } else if (req.url.includes("/__cool_modules")) {
          const dirs = fs.readdirSync(path.join(coolPath, "modules"));
          done({
            code: 1000,
            data: dirs.filter((e) => !e.includes("."))
          });
        } else {
          next();
        }
      });
    }
  };
};