IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> CsmWing源码分析(四) -> 正文阅读

[JavaScript知识库]CsmWing源码分析(四)

2021SC@SDUSC


此次继续分析文件src/controller/admin/model.js
该文件中的方法为模型操作,在整个项目中有着举足轻重的地位。

一、extAction()

我们使用一个map对象设置数据库查询时的条件: status 为 [’>’, -1] , ismod 为 1 。
countSelect 为分页查询,一般结合page方法一起使用。 data 是 map 限定条件下在数据库中的分页查询结果。data 的数据结构包括:pageSize(每页显示的条数),currentPag(当前页),count(总条数),totalPages(总页数),data(当前页下的数据列表)。
pagination 方法对 data 进行分页展示,存储在 html 中。
assign 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。第一次 assign 方法将 html 分配给 pagerData ,第二次 assign 方法将 data.data(当前页下的数据列表)分配给 list。
这个方法和上一篇里的 indexAction 几乎完全一致。

async extAction() {
    const map = {'status': ['>', -1], 'ismod': 1};
    const data = await this.db.where(map).page(this.get(`page`)).countSelect();
    const html = this.pagination(data);
    this.assign('pagerData', html); 
    this.assign('list', data.data);
    this.meta_title = '独立模型管理';
    this.tactive = 'ext';
    return this.display();
  }

二、extunAction()

think.getdirFiles 方法用于获取文件夹下的所有文件,此处将文件夹 ${think.APP_PATH}/controller/mod 里的所有文件放入数组中并赋值给dir。
对dir中的每一个元素进行处理并push到数组 modarr 的末尾。
借助 modarr ,我们可以找出未安装的插件和未安装插件的配置。
由此我们得到一个未安装的独立模型。

async extunAction() {
    const dir = think.getdirFiles(`${think.APP_PATH}/controller/mod`);
    console.log(dir);
    const modarr = [];
    for (const v of dir) {
      modarr.push(think._.head(think._.split(v, path.sep, 1)));
    }
    console.log(modarr);
    const uniarr = [];
    for (const d of think._.uniq(modarr)) {
      const map = {'status': ['>', -1], 'ismod': 1};
      map.name = d;
      const ism = await this.db.where(map).find();
      if (think.isEmpty(ism)) {
        uniarr.push(d);
      }
    }
    const unilist = [];
    for (const modName of uniarr) {
      unilist.push(think.app.controllers[`mod/${modName}/config`]);
    }
    console.log(unilist);
    this.assign('list', unilist);
    this.meta_title = '未安装的模型';
    this.tactive = 'ext';
    this.active = 'admin/model/ext';
    return this.display();
  }

三、installextAction()

此方法用于安装插件。
首先导入数据库文件,将数据库文件存放于变量 sqlpath 中。sqlpath 即数据库文件的路径,通过 think.isFile() 方法判断,若该路径下确实为文件,那么继续导入数据库。
后面大块的代码只有一个目的:导入数据库,包括数据库的各个表。
代码后面进行了异常处理,但是并没有进行具体的异常分析,而是直接笼统地 catch 了所有 exception ,并告诉系统:数据表导入失败,请在控制台下查看具体的错误信息,并在 GitHub 上发 issue。
若数据库导入成功,那么就可以添加数据模型。注意要添加模型添加的时间。
添加成功后,更新缓存,并给主进程发送重启的指令,方法结束,返回 success。

async installextAction() {
    const mod = this.get('mod');
    const modconfig = think.app.controllers[`mod/${mod}/config`];
    const sqlpath = path.join(`${think.APP_PATH}/controller/mod/${mod}`, `${mod}.sql`);
    if (think.isFile(sqlpath)) {
      const sqlfile = fs.readFileSync(sqlpath, 'utf8');
      let content = sqlfile.split(/(?:\r\n|\r|\n)/g).filter(item => {
        item = item.trim();
        const ignoreList = ['--', 'SET', '#', 'LOCK', 'UNLOCK', 'INSERT'];
        for (const it of ignoreList) {
          if (item.indexOf(it) === 0) {
            return false;
          }
        }
        return true;
      }).join('');
      content = content.replace(/\/\*.*?\*\//g, '');
      content = content.substring(0, content.length - 1);
      const arr = content.split(';');
      const insert = sqlfile.split(/(?:\r\n|\r|\n)/g).filter(item => {
        item = item.trim();
        if (item.indexOf('INSERT') === 0) {
          return true;
        }
        return false;
      });
      const sqlarr = arr.concat(insert);
      try {
        for (let item of sqlarr) {
          item = item.trim();
          if (item) {
            item = item.replace(/cmswing_/g, this.config('model.mysql.prefix') || '');
            think.logger.info(item);
            await this.model('mysql').execute(item);
          }
        }
      } catch (e) {
        think.logger.error(e);
        return this.fail('数据表导入失败,请在控制台下查看具体的错误信息,并在 GitHub 上发 issue。');
      }
    }
    modconfig.create_time = new Date().getTime();
    await this.model('model').add(modconfig);
    await update_cache('model');
    process.send('think-cluster-reload-workers');
    return this.success({name: '安装成功!'});
  }

四、addextAction()

此方法用于新建独立模型。
如果请求加载了数据,那么首先生成插件目录。需要注意的是,此插件目录需要生成,若该目录已存在,说明模型已经被建立(有可能是同名或者项目逻辑出现问题),此方法无法执行,返回错误信息。
获取post的数据,并设置数据的创建时间和更新时间。如果获取的数据 post.attribute_list 为数组,那么将它作为字符串返回,数组中的元素由分隔符“,”分隔。
变量res用于确定数据是否成功更新到数据库中。若更新成功,那么初始化表结构,并将模型添加到钩子;之后创建插件目录和钩子控制器(此处有一些尚未被完成的方法,主要是用钩子进行一些业务处理);最后,创建插件view目录、model目录、service目录、后台管理控制器、前台访问控制器,并更新缓存,告知系统更新模型成功。若更新失败,则告知系统更新模型失败
获取请求的信息,赋值给 data 。
如果没有请求加载数据,此方法也就没有意义了。

async addextAction() {
    if (this.isPost) {
      const data = this.post();
      const moddir = `${think.APP_PATH}/controller/mod`;
      const modpath = `${moddir}/${data.name}`;
      if (think.isDirectory(modpath)) {
        return this.fail(`${data.name} 模型目录已经存在`);
      };
      data.create_time = new Date().valueOf();
      data.update_time = new Date().valueOf();
      data.status = 1;
      data.ismod = 1;
      if (think.isArray(data.attribute_list)) {
        data.attribute_list = data.attribute_list.join(',');
      }
      const res = await this.db.add(data);
      if (res) {
        const addtable = await this.model('cmswing/attribute').addtable(res);
        if (!think.isEmpty(data.hooks)) {
          for (const h of data.hooks) {
            const hooks = await this.model('hooks').where({name: h}).find();
            let extarr = hooks.ext ? hooks.ext.split(',') : [];
            extarr.push(data.name);
            extarr = think._.uniq(extarr);
            await this.model('hooks').where({name: h}).update({ext: extarr.join(',')});
          }
        }
        think.mkdir(modpath);
        fs.writeFileSync(`${modpath}/config.js`, `module.exports = ${JSON.stringify(data)}`);
        const hookaction = [];
        if (!think.isArray(data.hooks)) {
          data.hooks = data.hooks.split(',');
        }
        for (const v of data.hooks) {
          const type = await this.model('hooks').where({name: v}).getField('type', true);
          console.log(type);
          if (Number(type) === 1) {
            hookaction.push(`/**
   * 实现的AdminIndex钩子方法
   * 【视图】
   * @param ...val
   */
  async ${v}(...val) {
    // 钩子业务处理
    const html = await this.hookRender('${v}', '${data.name}');
    return html;
  }`);
            const mvp = `${modpath}/view`;
            think.mkdir(`${mvp}/pc`);
            fs.writeFileSync(`${mvp}/pc/hooks_${v}.html`, `${data.name}`);
            think.mkdir(`${mvp}/mobile`);
            fs.writeFileSync(`${mvp}/mobile/hooks_${v}.html`, `${data.name}`);
          } else {
            hookaction.push(` // 实现的${v}钩子方法
  ${v}() {
    // 钩子业务处理
  }`);
          }
        }
        const hookhtml = hookaction.join(';\n  ');
        const hooksstr = `// hooks
module.exports = class extends think.cmswing.modIndex {
  ${hookhtml}
}`;
        fs.writeFileSync(`${modpath}/hooks.js`, hooksstr);
        this.copy(`${moddir}/demo/view`, `${modpath}/view`, this.copy);
        this.copy(`${moddir}/demo/model`, `${modpath}/model`, this.copy);
        this.copy(`${moddir}/demo/service`, `${modpath}/service`, this.copy);
        this.copy(`${moddir}/demo/logic`, `${modpath}/logic`, this.copy);
        this.copy(`${moddir}/demo/admin.js`, `${modpath}/admin.js`);
        this.copy(`${moddir}/demo/index.js`, `${modpath}/index.js`);
        await update_cache('model');
        return this.success({name: '添加成功', url: '/admin/model/ext'});
      } else {
        return this.fail('添加失败!');
      }
    } else {
      const hooks = await this.model('hooks').select();
      this.assign('hooks', hooks);
      this.tactive = 'ext';
      this.active = 'admin/model/ext';
      this.meta_title = '添加独立模型';
      return this.display();
    }
  }
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-03 12:57:17  更:2021-12-03 12:59:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:17:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码