## VentAnaly_2.0_front
系统v2.0前端代码仓库
### 前言
本项目以[jeecgboot](https://github.com/jeecgboot/jeecgboot-vue3)为模板,请先阅读此文档后继续!
### 开始
建议:安装 nvm 或其他 nodejs 版本管理器,使用 VSCode 作为 IDE,使用 Chrome/Edge 浏览器;
1. 在项目目录下执行 `pnpm install`
2. 在项目目录下执行 `git config commit.template .github/COMMIT_TEMPLATE`
### 开发
开发的基本流程,部分内容可忽略
`git pull` # 可以rebase
`git checkout [branch]` # 可选
`nvm use 20` # 建议,高版本node自带pnpm包管理器
`pnpm dev` # 必选,dddd
`git add .`
`git commit` # 公用模板见.github/COMMIT_TEMPLATE
`git push origin [branch]` # 目前master分支无保护,可直接推
### 构建
`pnpm build`
### 主题及主题化
主题可以在 /views/vent/sys/setting/index.vue 中找到设置入口
常规的颜色、变量在 /design/color.less 或 /design/themify/ 下添加,图片资源应在 /assets/images/themify/ 下添加
一般来说,主题化开发可以参考以下代码
```less
// import theme variables
@import '/@/design/theme.less';
// scope the selector
@{theme-deepblue} {
  .your-component-root-class-name {
    --image-a: url('/@/assets/images/themify/deepblue/a.png');
    --bg-a: #ffffff;
  }
}
// scope the selector
@{theme-dark} {
  .your-component-root-class-name {
    --image-a: url('/@/assets/images/themify/dark/a.png');
    --bg-a: #000000;
  }
}
// default css
.your-component-root-class-name {
  --image-a: url('/@/assets/images/a.png');
  --bg-a: #888888;
  .class-name-a {
    background-image: var(--image-a);
    background-color: var(--bg-a);
  }
}
```
更加详细的页面主题化标准模板可以参考登录页 /views/sys/login/Login.vue
如果已经写了css代码,想要支持主题化,则下面是配合主题化使用的工具,用于将已有样式代码输出为主题化代码。输入页面的 css 样式,即可输出标准模板所需的资源(返回的数据第一项为变量集合,第二项为css代码文本)
```javascript
// Take note of requires below before using this function:
// 1. replace all url patterns to patterns like `url(/@/xxx/xxx.xxx)`.
// 2. remove all the in-line comments(//) or replace them to block comments(/** */).
// 3. replace all rbg/rgba/hsa or any other css color functions to hex colors(#xxxxxx).
function themifyScript(
  str,
  options = {
    color: false,
    gradient: false,
    url: true,
  }
) {
  const keySet = new Set();
  let strcopy = str;
  let varstr = '';
  // process url, extract all css url and replace them to css var and record them.
  {
    keySet.clear();
    const regexp = /url\('?(\/[@|0-9|a-z|A-Z|\-|_]+)+.(png|svg)'?\)/g;
    let res = regexp.exec(str);
    while (res) {
      const [url, image] = res;
      const varname = `--image-${image.replace('/', '')}`;
      if (!keySet.has(image)) {
        keySet.add(image);
        varstr += `${varname}: ${url};`;
      }
      if (options.url) {
        strcopy = strcopy.replace(url, `var(${varname})`);
      }
      res = regexp.exec(str);
    }
  }
  // process gradient, extract all css gradient and replace them to css var and record them.
  {
    keySet.clear();
    let key = 0;
    const regexp = /linear-gradient\([0-9|a-z|A-Z|#|,|\s|%|.]+\)/g;
    let res = regexp.exec(str);
    while (res) {
      const [gradient] = res;
      const varname = `--gradient-${key}`;
      if (!keySet.has(gradient)) {
        keySet.add(gradient);
        varstr += `${varname}: ${gradient};`;
      }
      if (options.gradient) {
        strcopy = strcopy.replace(gradient, `var(${varname})`);
      }
      res = regexp.exec(str);
      key += 1;
    }
  }
  {
    keySet.clear();
    let key = 0;
    const regexp = /radial-gradient\([0-9|a-z|A-Z|#|,|\s|%|.]+\)/g;
    let res = regexp.exec(str);
    while (res) {
      const [gradient] = res;
      const varname = `--gradient-${key}`;
      if (!keySet.has(gradient)) {
        keySet.add(gradient);
        varstr += `${varname}: ${gradient};`;
      }
      if (options.gradient) {
        strcopy = strcopy.replace(gradient, `var(${varname})`);
      }
      res = regexp.exec(str);
      key += 1;
    }
  }
  // process color, extract all css colors and replace them to css var and record them.
  {
    keySet.clear();
    let key = 0;
    const regexp = /#[0-9|a-z|A-Z]{3,8}/g;
    let res = regexp.exec(str);
    while (res) {
      const [color] = res;
      const varname = `--color-${key}`;
      if (!keySet.has(color)) {
        keySet.add(color);
        varstr += `${varname}: ${color};`;
      }
      if (options.color) {
        strcopy = strcopy.replace(color, `var(${varname})`);
      }
      res = regexp.exec(str);
      key += 1;
    }
  }
  return [varstr, strcopy];
}
```
### SVG模型动画开发
关于svg二维模型动画开发,核心方法之一位置为/mky-vent-base/src/hooks/vent/useSvgAnimation.ts,说明如下:
1、设计团队提供svg图组,通常是一组svg图片,每张图片对应一个动画帧
2、将图组放入指定脚本的工作区内生成可用的vue组件,脚本可见项目的README文档,然后自行新建文件、复制代码、安装依赖并运行
3、将可用的vue组件引入到需要使用动画的页面中,并使用useSvgAnimation钩子进行动画控制,例如``
4、通过浏览器的元素检查功能,找到svg对应的group,复制group的id,并使用该id进行动画控制,详细可见步骤2中生成的组件的`animate`方法注释
使用示例:
```vue
  
```
上述的生成组件的脚本如下,注意脚本需要独立安装依赖运行:
```javascript
const fs = require('fs');
const path = require('path');
const { parseString } = require('xml2js');
const { Builder } = require('xml2js');
/**
 * 解析命令行参数
 * 支持 --keys=key1,key2 格式的参数
 * @returns {Object} 包含解析后参数的对象
 */
function parseArgs() {
  const args = process.argv.slice(2);
  const params = {};
  args.forEach((arg) => {
    if (arg.startsWith('--keys=')) {
      // 分割并处理keys参数
      params.keys = arg.split('=')[1].split(',');
    }
  });
  return params;
}
/**
 * 读取并解析SVG文件
 * @param {string} filePath - SVG文件路径
 * @returns {Promise