しがないPGの自衛記録

基本ずっと寝てる

Electron+Vue.jsで日報ファイル作成アプリを作ってみた

f:id:ashitaka1963:20200428072704p:plain

はじめに

こちらの記事で毎日投稿している?日報記事のベースとなるファイルを自動で作成するスクリプトを作成しました。

しかし、スクリプトの仕様として実行した日付が設定されるので、前日のものを作成したい場合などにはわざわざ日付を変えたりと使いづらくなりました。

なので、最近勉強しはじめたVue.jsを使ってGUIアプリケーションを作成していきたいと思います。

本記事のゴール

pythonスクリプトと同等の機能を持つアプリケーションを作成する。 (同等機能なので今のところはpythonスクリプト実行したほうがはやいけど。。。)

環境

  • Windows 10 64bit
  • node v12.16.2
  • npm 6.14.4

利用ライブラリ

  • Element : 2.13.1
    • デスクトップUIライブラリ

事前準備

element-uiインストール

element-uiをローカルインストールするために以下のコマンドを実行する。

>npm install  element-ui

日報アプリの実装手順

これ以降は、前回作成した環境から変更した部分のみを書いています。

ソースコード全文を見たい方は、Githubをご確認ください。

github.com

ファイル構成

# 一部のみ記載
create_templete_file
├── resource
│   └── templete.md
└── src
    ├── assets
    │   └── logo.png
    ├── components
    │   └── WriteFile.vue
    ├── App.vue
    ├── background.js
    └── main.js

main.js

インストールしたelement-uiを使用できるようにするためにmain.jsに以下を追加します。

// element-ui のimport
import ElementUI from 'element-ui'

// element-ui の言語を日本語に設定(デフォルト:中国語)
import locale from 'element-ui/lib/locale/lang/ja'

// element-ui のCSSをimport
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI, {locale})

background.js

DevToolsは必要ないので、26行目の以下をコメントアウトします。

if (process.env.WEBPACK_DEV_SERVER_URL) {
  // Load the url of the dev server if in development mode
  win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
  // if (!process.env.IS_TEST) win.webContents.openDevTools() ←ここをコメントアウト
} else {
  createProtocol('app')
  // Load the index.html when not in development
  win.loadURL('app://./index.html')
}

App.vue

前回はHelloWorld.vueという単一コンポーネントを読み込んでいた箇所を専用のコンポーネントに変更しています。

<template>
  <div id="app">
    <WriteFile/>
  </div>
</template>

<script>
import WriteFile from './components/WriteFile.vue'

export default {
  name: 'App',
  components: {
    WriteFile
  }
}
</script>

components/WriteFile.vue

メインとなるコンポーネントファイルになります。

<template>
  <el-main>
    <!-- ファイル名入力欄 -->
    <el-input placeholder="ファイル名を入力してください。" v-model="input" class="input-with-select">
      <el-select v-model="select" slot="append" placeholder="Select">
        <el-option label=".md" value=".md"></el-option>
        <el-option label=".txt" value=".txt"></el-option>
      </el-select>
    </el-input>

    <!-- 本文入力欄 -->
    <el-input
      type="textarea"
      :rows="2"
      :autosize="{ minRows: 10, maxRows: 50}"
      placeholder="Please input"
      v-model="textarea">
    </el-input>

    <!-- ファイル読み込みボタン -->
    <el-button type="primary" @click="readTempleteFile()">ファイル読み込み</el-button>
    <!-- ファイル書き出しボタン -->
    <el-button type="success" @click="writeFile()">ファイル書き出し</el-button>
  </el-main>
</template>

<script>
  export default {
    data () {
      return {
        taskList: [],
        input: '',
        select: '.md',
        textarea: ''
      }
    },
    methods: {
      // テンプレートファイル読み込み
      readTempleteFile(){

        // 初期化
        this.textarea=""

        // 現在日付取得
        var dt = new Date();
        var yyyy = dt.getFullYear();
        var mm= ("00" + (dt.getMonth()+1)).slice(-2);
        var dd = ("00" + dt.getDate()).slice(-2);
        var dayOfWeek = dt.getDay() ; // 曜日(数値)
        var dayOfWeekStr = [ "日", "月", "火", "水", "木", "金", "土" ][dayOfWeek]; // 曜日(日本語表記)

        // パス設定
        const path = require('path');
        const basePath = process.cwd();
        const templeteFilePath = path.resolve(basePath, './resource/templete.md');

        // テンプレートファイル読み込み
        const fs = require('fs');
        var readline = require("readline");
        var stream = fs.createReadStream(templeteFilePath, "utf8");
        var reader = readline.createInterface({ input: stream });

        let isFileNameFlg =true;
        reader.on("line", (line) => {

          // ======= 変換仕様 =======
          // 日付変換(yyyymmdd)
          if ( line.match(/yyyymmdd/)) {
            var replaceStr =  yyyy + mm + dd;
            line = line.replace( "yyyymmdd", replaceStr );
          }

          // 日付変換(yyyy年mm月dd日(Day))
          if ( line.match(/yyyy年mm月dd日(Day)/)) {
            replaceStr =  yyyy + "年"+ mm + "月" + dd + "日" + "(" + dayOfWeekStr + ")";
            line = line.replace( "yyyy年mm月dd日(Day)", replaceStr );
          }

          // 1行目の判定
          if (isFileNameFlg) {
            this.input = line;
            isFileNameFlg =false;
          }else{
            this.textarea += line
            this.textarea += '\n'
          }
        });
      },
      // ファイル書き出し
      writeFile () {
        const fs = require('fs');
        fs.writeFileSync(this.input +this.select, this.textarea);

        this.$message({
          message: 'ファイルが正常に出力されました。',
          type: 'success'
        });
      },
    }
  }
</script>

<style scoped>
  main.el-main {
    width: 600px;
    margin: 0px auto;
  }
</style>

<style>
  .el-select .el-input {
    width: 70px;
  }
  .input-with-select .el-input-group__prepend {
    background-color: #fff;
  }
</style>

完成品

こちらが完成品になります。

機能

今回作った日報作成アプリの機能は以下になります。

現時点では、2つの変換仕様にそってテンプレートファイルの内容が変換されます。

  • ファイル読み込みボタンをクリックすることで、resource配下のtemplete.mdファイルを読み込み画面に表示する。
  • テンプレートファイルの仕様
    • 1行目:ファイル名
    • 2行目以降:本文
  • 変換仕様
    • yyyymmdd ⇒ ex) 20200426
    • yyyy年mm月dd日(Day) ⇒ ex) 2020年04月26日(日)
  • ファイル書き出しボタンをクリックすることで、create_templete_file配下にファイルを出力する。

デモ

f:id:ashitaka1963:20200428073533g:plain

まとめ

とりあえず、pythonスクリプトと同じことができるGUIアプリケーションは作成できました。

まだまだ以下のような課題はあるので、少しずつ改修していきたいと思います。

ビミョーなところ

  • UIがいまいち。
  • 実行ファイル形式exeにすると、上手く動作しない。(テンプレートファイルの読み込み先が固定なため)
  • ソースコードがぐちゃぐちゃ。
  • 変換仕様の文字列は全て変換されてしまう。
  • ファイル出力場所がプロジェクトフォルダの直下に固定なところ。

改善したいこと

  • テンプレートファイルの読み込み場所を動的に変更できるようにする。
  • 出力ファイルの出力先を動的に変更できるようにする。
  • 関数化する。(変換部分など)
  • 文字列の置き換え対象のルールを作成する。