Vue3 + TS + Electron开发一个买房首付小工具

882 阅读1分钟

这是我参与更文挑战的第5天,活动详情查看: 更文挑战

初衷是为xdm在不暴露个人信息的情况下,对比小金库买房,给女票一个惊喜。首付小工具是以大连市作为模板,欢迎兄弟们PR。

新建项目

Vue3 + TS初始化

执行脚本:

yarn create @vitejs/app <project-name> --template vue-ts
cd <project-name>
yarn
yarn dev

Electron + TS初始化

新建electron目录以及相关文件

mkdir electron
cd electron
touch main.ts
touch preload.ts
touch render.ts

初始化electron相关代码

main.ts

import { app, BrowserWindow } from "electron";
import * as path from "path";
function createWindow() {
  const mainWindow = new BrowserWindow({
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
    },
    width: 800,
  });

  mainWindow.loadFile(path.join(__dirname, "..", "dist/index.html"));

  mainWindow.webContents.openDevTools();
}
app.on("ready", () => {
  createWindow();

  app.on("activate", function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
  }
});

preload.ts

window.addEventListener("DOMContentLoaded", () => {
  const replaceText = (selector: string, text: string) => {
    const element = document.getElementById(selector);
    if (element) {
      element.innerText = text;
    }
  };

  for (const type of ["chrome", "node", "electron"]) {
    replaceText(
      `${type}-version`,
      process.versions[type as keyof NodeJS.ProcessVersions] as string
    );
  }
});

配置执行脚本

新建tsconfig.electron.json

{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "outDir": "build",
        "noEmit": false,
        "module": "commonjs",
        "baseUrl": ".",
        "sourceMap": false,
    },
    "include": ["electron"]
}

修改vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [vue()],
  base: "./",
});

修改package.json

{
    main: "build/main.js",
    "scripts": {
        ...
        "build": "vite build",
        "dist:all": "npm run build && electron-builder --mac --linux --windows",
        "dev:electron": "npm run build && tsc -p tsconfig.electron.json && electron ./build/main.js"
    },
}

目前这种方式没有支持热更新,如有解决方案会更新。目前貌似有这个解决方案

首付计算页面

App.vue

<template>
  <div>
    <div>{{ sumPrice }}</div>
    <el-form ref="form" :model="form" :rules="rules">
      <el-form-item label="房子所占面积">
        <el-input
          v-model="form.house_size"
          type="'number'"
          placeholder="请输入房子所占面积"
          controls-position="right"
        ></el-input>
      </el-form-item>
      <el-form-item label="房子总价格">
        <el-input
          v-model="form.house_price"
          type="'number'"
          placeholder="请输入房产总价格"
          controls-position="right"
        ></el-input>
      </el-form-item>
      <el-form-item label="需付首付比例" prop="first_rate">
        <el-input
          v-model.number="form.first_rate"
          type="'number'"
          placeholder="请输入需付首付比例"
        ></el-input>
      </el-form-item>
      <el-form-item label="中介收费占比">
        <el-input
          v-model="form.mediation_price"
          type="'number'"
          placeholder="请输入中介收费占比"
        ></el-input>
      </el-form-item>
      <el-form-item label="契税">
        <el-input
          v-model="form.deed_tax"
          type="'number'"
          placeholder="请输入契税占比"
        ></el-input>
      </el-form-item>
      <el-form-item label="贷款方式">
        <el-radio-group v-model="form.load_method">
          <el-radio label="business">商业贷款</el-radio>
          <el-radio label="fund">组合贷款(公积金贷款 + 商业贷款)</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>
    <el-form ref="fundForm" :model="fundForm" :rules="fundRules" v-if="form.load_method === 'fund'">
      <el-form-item label="公积金贷款金额">
        <el-input
          v-model="form.fund_price"
          type="'number'"
          placeholder="请输入公积金贷款金额"
        ></el-input>
      </el-form-item>
      <el-form-item label="商业贷款金额">
        <el-input
          v-model="form.business_price"
          type="'number'"
          placeholder="请输入商业贷款金额"
        ></el-input>
      </el-form-item>
      <el-form-item label="商业贷款利率">
        <el-input
          v-model="form.business_rate"
          type="'number'"
          placeholder="请输入商业贷款利率"
        ></el-input>
      </el-form-item>
    </el-form>
    <el-button @click="handleHouseFirstPrice">计算首付</el-button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import {
  ElForm,
  ElFormItem,
  ElInput,
  ElRadio,
  ElRadioGroup,
  ElButton,
} from "element-plus";

export default defineComponent({
  name: "App",
  components: {
    ElForm,
    ElFormItem,
    ElInput,
    ElRadio,
    ElRadioGroup,
    ElButton,
  },
  data() {
    const validateFirstRate = (
      rule: any,
      value: string,
      callback: Function
    ) => {
      const numValue = parseFloat(value);
      if (!Number.isInteger(value)) {
        callback(new Error("请输入数字值"));
      } else if (numValue > 1 || numValue <= 0) {
        callback(new Error("请输入数字值满足 ===> 大于0 小于等于1"));
      } else {
        callback();
      }
    };
    return {
      form: {
        house_price: undefined,
        mediation_price: undefined,
        first_rate: undefined,
        deed_tax: undefined,
        house_size: undefined,
      },
      fundForm: {
        fund_price: undefined,
        business_price: undefined,
        business_rate: undefined,
        fund_safe: 2000
      },
      rules: {
        first_rate: [{ validator: validateFirstRate, trigger: "blur" }],
      },
    };
  },
  computed: {
    sumPrice() {
      const house_price: number = this.$data.form.house_price || 0;
      const mediation_price: number = this.$data.form.mediation_price || 0;
      const first_rate: number = this.$data.form.first_rate || 0;
      const deed_tax: number = this.$data.form.deed_tax || 0;
      const firstMoney = house_price * first_rate;
      const mediationMoney = house_price * mediation_price;
      const deedTaxMoney = house_price * deed_tax;
      return firstMoney + mediationMoney + deedTaxMoney;
    },
  },
  methods: {
    handleHouseFirstPrice() {
      console.log(this.$data.form);
    },
  },
  mounted() {},
});
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

打包

安装electron-builder

yarn add electron-builder -D
npm run dist:all

修改package.json

{
    "build": {
        "appId": "com.zy.www",
        "directories": {
          "output": "software"
        },
        "files": [
          "build/**/*",
          "dist/**/*",
          "package.json"
        ]
  }
}