🐟摸鱼集|我与文档势不两立

1,290 阅读8分钟

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

天天说摸鱼,还没整理摸鱼成果,把这段干货整理了一下,算是有验证有结尾的闭环,放心看、放心用童叟无欺

  • 关于日常工作中程序最讨厌的文档如何摸鱼交付的问题
  • 关于雇个机器人帮你写代码的多点时间摸鱼的问题
  • 关于excel、word格式及内容互转的问题

前情回顾

文档交付

一路coding,接触过90%的程序都对文档深恶痛绝,我也不例外,可偏偏经历过一个全能岗,非要让我一个搞程序的和别人吃饭10几年的文档技能同台竞技、时间和精力不足又得在放大镜下交付,不得不分出精力去弱化格式,专注内容。

机器人帮手

有点儿夸大嫌疑,主要是这玩意儿实践得多,确实对我的成长还有工作获益良多,当前我的实践方案,从5-30代码生成代码算起来,差不多刚过了40天左右,如果刨除工作日及节假日再加其他调研实践,按平均3小时每天(实际上可能更少),120/8也就是前后15天左右,包含服务联调测试,我完成了项目前端部分的重写,外加地图导航、补充组件的功能的设计开发,之前其他平台上有质疑认为没法维护和继续开发,那么现在我可以肯定的答复,交付的同时,也保留了后续的批量能力。
我始终秉持着,个人工作的吞吐量,完全是由你储备的摸鱼工具多少决定的

💢关于网吹的低代码,看过一个很经典的总结,原话记不清了,开发很不爽、运维火葬场、交付狗不用、一改全操翻。(抱歉,容我废话吐槽一下)

鼻祖asp.net、dreamweaver 拖拉拽已经算是顶级了,不知道是网络7秒鱼记忆发功了,还是有什么新特性

低代码开发平台的出现给应用程序开发行业带来了一场新的革命,改变了传统应用程序开发的模式,很多人都在想低代码开发平台为什么会对企业应用程序开发产生影响呢?你知道低代码开发平台对于企业IT架构有什么作用吗?下面一起来了解一下相关的知识吧!

数据架构和移动策略

逻辑思维与流程管理

低代码开发因其灵活的开发方式,可以有效地解决开发过程中需求变更,人为错误导致的损失,及时止损,缩短开发周期

前几年可能有点儿作用,现在属于公狮的头发装头大,在固有的框架体系内,想要保证灵活性,真的当甲方爸爸是活菩萨,现在的编排工具扎堆出现,是需求灵活性增强的现象,asp.net、dreamweaver普及面编变小,固然有前端工程化的影响,但最重要的还是迭代频率跟不上,何至于相信小型插件维护能比得过大型公司,怕不是都拿人当傻子

至于搞开发的为什么厌恶,一方面是抢地盘、一方面主因是楼建的很高了,非要我跳到楼下拿工具做修饰

如果目的是提效,我实在没搞明白这个和代码生成器的差别在哪里,或者应该叫l带配置的代码生成器?

好了,停止吐槽,继续往下

文档多份交付偷鸡模式

项目过程中,功能列表.xlsx、交付标准套件(至少5份).docx 多交付,格式处理等问题,基本都会遇到,特别涉及到协同和修改的时候,格式处理都要蜕层皮,由此衍生了这套摸鱼方案

以前的解决方案

1.之前关于文档格式以及编号的处理,基本上自己搞的话用的是odt模板进行文档格式化,程序处理基本用apose.word对格式进行精准控制

2.关于机器人帮手,前后端整项目生成用CodeSmith Tools,单表基准生成还勉强,主要有点儿笨重

3.文档多分交付问题,一般会用文本域去定制一些如项目名之类的,避免内容多改错,绝大部分要耗费很大精力调样式,基本多人协作,版本就有很多分,太不仁道了

实战

分析主因

  • 搞程序的基本思维都会缜密一些,考虑的比较全面,这从另外一方面也限制了自身,发散能力不足,产品和市场能各种夸海口吹牛皮,我们不敢,一旦吹出去,基本就是挖坑埋自己,所以文档会显得小家子气
  • 开发任务繁重,本身文档也不是主要工作,再加上也没特意去点那个技能,既排斥也写不好,之前国企里面搞10多年文档的人跟我聊过,说文档要有架构,我当时很震惊,吹牛B的吧,也是最近才认同,因为搞程序的真的干不过玩PPT的,当然我这里是佩服,心悦诚服那种。
  • 没实际经历过,我们像是被封印在一个功能、一个系统中,如果之前没有接触过,是真的get不到那个点,我头一次换公司时,死活理解不了,为什么一个系统会需要几百个开发去维护,当我编译历史系统耗费了近1个小时后,格局被打开了
  • 不得不承认,搞程序的固执且高傲,内心其实本能的鄙视写文档,认为这项时杂活儿,属于不务正业
    以上造成了一个委屈的现实,我看不上,但我又不得不做

说说思路,你也许会喜欢

一统工具

markdown极客风、excel相对接收程度会高一些,功能梳理划分基本习惯于excel,很多公司的建表sql也习惯用excel去处理,当然我对excel的爱就跟格子衬衫一样情不自禁,内心外显化

搞前端相信你对vscode不陌生,像我这种非专业的懒货,尝鲜的java项目也在这上面整

image.png 再比如当前的内容也是在这上头一块搞定的

突出一个”能用一个,我绝不用两个,能走直线,我绝不绕弯“

来点儿自定义

这块有3个点:

  1. markdown拷贝复制时,本地图片的问题
  2. 读取excel转为word结构(树结构的转置)
  3. markdown内容自定义word文档格式
{
  "scripts": {
    "tansmd":"node helper\tans.js E:\文档\markdown\博客\组态,你值得拥有.md",
    "readxls":"node helper\readXls.js&&pandoc  a.md -o a.docx --reference-doc=工作/custom-reference.docx ",
    "tansDocx":"cd/d 工作 pandoc  xx.md -o xx.docx --reference-doc=custom-reference.docx"
  },
  "dependencies": {
    "commander": "^9.3.0",
    "mime-types": "^2.1.35",
    "mkdirp": "^1.0.4",
    "node-xlsx": "^0.21.0"
  },
  "devDependencies": {
    "chalk": "^4.1.2"
  }
}

上个效果

把src原本的文件连接换成base64,当然也有另外一种,放在文件末尾,此处不纠结看后续

文档转markdown主体,再通过pandoc转定制格式的docx,这两种互转比较常见,

function transBase64(file){
  let filePath = path.resolve(file); // 原始文件地址
  let fileName = filePath.split('\').slice(-1)[0].split('.'); // 提取文件名
  let fileMimeType = mimeType.lookup(filePath); // 获取文件的 memeType

  // 如果不是图片文件,则退出
  if (!fileMimeType.toString().includes('image')) {
    console.log(chalk.red(`Failed! ${filePath}:\tNot image file!`));
    return;
  }
  // 读取文件数据
  let data = fs.readFileSync(filePath);
  data = new Buffer(data).toString('base64');

  // 转换为 data:image/jpeg;base64,***** 格式的字符串
  let base64 = 'data:' + fileMimeType + ';base64,' + data;
  return base64;
 }

 async function replaceUrl(file){
   /**
    * 1.读取md文件
    * 2.正则匹配图片路径
    * 3.转换路径未base64
    * 4.替换路径为base64
    * 5.另存为新文件
    */
  let content =await fs.readFileSync(file, 'utf8');
  let uw=content.replace(/![.*]((.*?))/g, function(word){
   const path= word.match(/![.*]((.*?))/)[1];
    let base64= transBase64(path);
    return word.replace(path,base64);
  }
  );
  writeIfModified('./tmp.md',uw);
 }
var xlsx = require('node-xlsx');
const chalk = require('chalk'); // 带色彩的控制台输出
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');

global.writeIfModified = function (filename, newContent) {
    let filePath = path.resolve(filename); // 原始文件地址
    try {
      const oldContent = fs.readFileSync(filePath, 'utf8');
      if (oldContent == newContent) {
        console.warn(`* Skipping file '${filename}' because it is up-to-date`);
        return;
      }
    } catch (err) {
    }
    if (['0', 'false'].indexOf(process.env.DRY_RUN || '0') !== -1) {
      fs.writeFileSync(filePath, newContent);
    }
    console.warn(`* Updating outdated file '${filename}'`);
  };

/**
 * 读取excel
 * @param {*} path 
 */
function read(path,callbackrow){
    // 解析得到文档中的所有 sheet
    var sheets = xlsx.parse(path);
    // 遍历 sheet
    sheets.forEach(function(sheet){
  
        // 读取每行内容
        for(var rowId in sheet['data']){
            var row=sheet['data'][rowId];
            if(callbackrow)callbackrow(row,rowId);
        }
        console.log(chalk.green(sheet['name'],sheet['data'].length,'条记录'));
    });
}

/**
 * 解析excel行列
 */
var hansh=[];
var indexOrder=0;
read('E:\文档\markdown\博客\1.xlsx',function(row,index){
   if(index<1)return 
   const [systemname,title,content]=row;
   var indexPre='4.2.';
   if(systemname){
      const tmpnmae= systemname.split(':')[0];
      indexOrder++;
     hansh.push(`## ${indexOrder} ${tmpnmae}
    ${systemname.split(':').length>1?systemname.split(':')[1]:''}
    `)
   }
    if(title){
        hansh.push(`### **${title}**:${content?content:''}`);
    }
    // if(content){
    //     hansh.push(`\n${content}`);
    // }
});

writeIfModified('a.md',hansh.join('\n'))

代码工具

此处就不占篇幅了,之前有写代码生成代码,主要是通过分析代码转为excel+json,再通过ejs批量生成的
工作开发模式为,页面基本稳定后,主要免去绑字段和接口对应,基础页面逻辑,在基础版本上迭代开发

补充插件说明

Pandoc,如何下载安装就不赘述了,Typora用的就是这玩意儿

数据库设计文档导出

但你懂得,PDManer应该有的老哥在常用,代码生成部分真的一言难尽,重点说下导出

最后补充一个盘符文件扫描

tree /f >a.xlsx
dir /b /s  >dir.xlsx

结束语

绝大部分搞程序的老哥,不可能一点儿文档都不碰,这属于被动技能点,希望会帮到为此困扰的老哥,多点儿摸鱼学习时间,另外markdown本地图片的问题有一些延申,准备搞个google插件,便于内容发布、
PS:顺手甩个赞、关注不迷路、实战实分享、多点儿摸鱼怪!!

往期目录