CsmWing source code analysis

Keywords: Front-end


This time, we will analyze the file src/controller/admin/model.js
The method in this document is model operation, which plays an important role in the whole project.

1, editextAction

This method is used to edit a stand-alone model.

If the request loads data, get the post data and set the update time of the data. If the obtained data is post.attribute_ If list is an array, it is returned as a string, and the elements in the array are separated by the separator ",".
The variable res is used to determine whether the data is successfully updated to the database. If the update is successful, add the model to the hook and update the hook. Then generate or update the configuration file, update the cache, and inform the system that the model update is successful.

If there is no request to load data, obtain the id, find a single piece of data in the database according to the id, and assign it to data. If the attribute of data_ If the list is not empty, we will attribute_list is divided into string arrays according to "," and ".
Instantiate the model attribute and find the model_id = data.id, the fields are limited to id,name,title,is_show multiple pieces of data, and assign the obtained data to fields.
Determine whether data inherits other models. If other models are inherited, the corresponding data will be obtained and assigned to extend_field and extend_field and fields are merged and assigned to allfields; Otherwise, assign fields to allfields.
Use the JSON.parse() method to convert data.field_sort is converted to a JavaScript object and assigned to field_sort.
Finally, the variables fields, extend_ The values in fields, orderbgy, data are assigned to the model fields' fields' and 'extend'_ Fields', 'allfields',' info ', the method ends and returns.

It can be found here that the logic of the edit independent model method here is basically the same as that in the previous article, except for some methods related to hooks. The specific analysis of the hook can be found in the blog of the same group of students, which will not be repeated here.

async editextAction() {
    if (this.isPost) {
      const post = this.post();
      post.ismod = 1;
      post.update_time = new Date().valueOf();
      if (think.isArray(post.attribute_list)) {
        post.attribute_list = post.attribute_list.join(',');
      if (!think.isEmpty(post.hooks) && think.isArray(post.hooks)) {
        post.hooks = post.hooks.join(',');
      const res = await this.db.update(post);
      if (res) {
        if (!think.isEmpty(post.hooks)) {
          for (const h of post.hooks.split(',')) {
            const hooks = await this.model('hooks').where({name: h}).find();
            let extarr = hooks.ext ? hooks.ext.split(',') : [];
            extarr = think._.uniq(extarr);
            await this.model('hooks').where({name: h}).update({ext: extarr.join(',')});
        const configs = await this.model('model').fieldReverse('id').find(post.id);
        const moddir = `${think.APP_PATH}/controller/mod`;
        const modpath = `${moddir}/${configs.name}`;
        fs.writeFileSync(`${modpath}/config.js`, `module.exports = ${JSON.stringify(configs)}`);
        await update_cache('model');
        return this.success({name: 'Update model succeeded!', url: '/admin/model/ext'});
    } else {
      const id = this.get('id');
      let allfields;
      if (think.isEmpty(id)) {
        this.fail('Parameter cannot be empty!');
      const data = await this.db.find(id);
      data.attribute_list = think.isEmpty(data.attribute_list) ? '' : data.attribute_list.split(',');
      const fields = await this.model('attribute').where({model_id: data.id}).field('id,name,title,is_show').select();
      if (data.extend != 0) {
        var extend_fields = await this.model('attribute').where({model_id: data.extend}).field('id,name,title,is_show').select();
        allfields = fields.concat(extend_fields);
      } else {
        allfields = fields;
      for (const field of allfields) {
        if (!think.isEmpty(data.attribute_list) && !in_array(field.id, data.attribute_list)) {
          field.is_show = 0;
      var obj = {};
      if (allfields) {
        for (const v of allfields) {
          obj[v.id] = v;
      } else {
        for (const v of fields) {
          obj[v.id] = v;
      const field_sort = JSON.parse(data.field_sort);
      if (!think.isEmpty(field_sort)) {
        for (const group in field_sort) {
          field_sort[group].forEach((v, k) => {
            if (obj[v]) {
              obj[v].group = group;
              obj[v].sort = k;

      const order = think._.values(obj);
      const orderbgy = think._.orderBy(order, ['group', 'sort'], ['asc', 'asc']);
      if (!think.isEmpty(data.hooks)) {
        data.hooks = data.hooks.split(',');
      const hooks = await this.model('hooks').select();
      this.assign('hooks', hooks);
      this.assign({'fields': fields, 'extend_fields': extend_fields, 'allfields': orderbgy, 'info': data});
      this.tactive = 'ext';
      this.active = 'admin/model/ext';
      this.meta_title = 'Edit model';
      return this.display();

2, Unextextaction

This method is used to unload a stand-alone model.
First, get the id, find a single piece of data in the database according to the id, and assign it to M. According to m, we can judge whether the database table of the database is empty through think.isEmpty(m.table). If it is not empty, it will be deleted. Then we find and delete the data through the database: delete the classification of the model, clear the search index, clear the search configuration, and clear the topic data.
Finally, delete the whole model and update the cache, telling the system "uninstall succeeded, move to not installed!"

async unextAction() {
    const id = this.get('id');
    const m = await this.model('model').find(id);
    if (!think.isEmpty(m.table)) {
      await this.deltable(m.table.split(','), m.name);
    const cats = await this.model('category').where({model: m.id}).getField('id');
    if (!think.isEmpty(cats)) {
      await this.model('category').where({id: ['IN', cats]}).delete();
      console.log('Delete classification');
      await this.model('category_priv').where({catid: ['IN', cats]}).delete();
      console.log('Clear classification permissions');
    await this.model('search').where({m_id: m.id}).delete();
    console.log('Clear search index');
    await this.model('search_model').where({mod: m.id}).delete();
    if (m.key_show === 1) {
      await this.model('keyword_data').where({mod_id: m.id}).delete();
      console.log('Clear topic data');
    await this.model('model').where({id: m.id}).delete();
    await update_cache('model');
    return this.success({name: 'Uninstall succeeded, move to not installed!'});

3, delextAction

This method is used to delete the plug-in.
First, judge whether the plug-in is allowed to be deleted according to mod. If mod is equivalent to 'demo', it is not allowed to be deleted. If deletion is allowed, obtain the data in the corresponding directory for subsequent operations.
Get the tables in the database from data. If the database is not empty, delete the tables and databases in the database. After the deletion is completed, send a restart instruction to the main process to inform the system that the deletion is successful.
The method to delete a table is the deltable() method, which is a custom method.

async delextAction() {
    const mod = this.get('mod');
    if (mod === 'demo') return this.fail('Deletion not allowed');
    const modpath = `${think.APP_PATH}/controller/mod/${mod}`;
    const data = think.app.controllers[`mod/${mod}/config`];
    const tables = data.table;
    if (!think.isEmpty(tables)) {
      await this.deltable(tables.split(','), mod);
    await think.rmdir(modpath).then(() => {
      console.log('Delete complete');
    return this.success({name: 'Delete succeeded!'});

Posted by The MA on Thu, 02 Dec 2021 10:53:16 -0800