Дизайн и реализация функции конфигурации приложения Dahua

задняя часть

В процессе участия в разработке различных бизнесов приложений большинство из них столкнется с необходимостью гибкого управления фоновым управлением теми или иными функциями/интерфейсами/данными.Клиент меняется в соответствии с изменениями конфигурации, и эти потребности могут быть решены без выдача версий.Общее функциональное требование состоит в том, чтобы предоставить фоновую функцию, которая может настраивать и управлять продуктом/работой детской обуви, а затем выводить его клиенту для логики/рендеринга через интерфейс сервера.Здесь мы разделяем относительно общий решение для этого сценария.

история проекта

Текущий проект для нужд этой конфигурации, каждый раз требующий от разработчиков переделывать фоновую форму, а затем изменять интерфейс конфигурации для выходной конфигурации, потому что функции разработки должны быть дома давным-давно, я не знал, зачем быть так и делай, проблемы сейчас не простые в обслуживании и расширении, а так же дублирование затрат на разработку

Организуйте свои потребности

  • История управления конфигурацией
    • Поддержка контроля версий
    • Поддерживаемые типы клиентов (Android/IOS/все)
    • Формы настраиваются
  • Настройте выходной интерфейс
    • Инкрементная поставка
    • Гарантированная высокая доступность, высокая стабильность, высокая производительность
  • клиент
    • Интерфейс предоставляет данные конфигурации для кэширования

техническое образование

  • Фон управления: php server + jquery + bootstrap
  • Проект интерфейса: php сервер

технический процесс

  • Выбор передовой технологии:

    • vuejs
    • element ui
  • Основной вопрос, как настроить сгенерированную форму в фоновом режиме (настраивается разработчиком)?

Первоначальный план состоит в том, чтобы сгенерировать форму пользовательского интерфейса элемента, настроив JSON формы.После некоторых исследований я также нашел библиотеку js, которая может сгенерировать форму пользовательского интерфейса элемента, настроив JSON.Это также большая проблема, поэтому устарело. Я попытаюсь реализовать это позже. Функция этой формы конфигурации реализована относительно простым способом через компонент vuejs + element ui, который может поддерживать основные потребности. Подробности см. В коде (простой и грубый)

  • Инкрементная доставка данных интерфейса, а также время привлечения клиентов и стратегия кэширования

При каждом запуске клиент получает конфигурацию, кэширует [данные конфигурации], добавляет в кэш новые конфигурации и заменяет существующие.
Когда интерфейс выводит [данные конфигурации], заголовок ответа [отметка времени] = с отметкой времени сервера текущего запроса
Клиент получает данные и кэширует [данные конфигурации] и [метку времени]
В заголовке следующего запроса клиента будет [timestamp] = кешированная метка времени, первый запрос можно не указывать
Когда сервер получает запрос, он получает [отметку времени] клиента и при фильтрации конфигурации проверяет, что время последнего обновления >= [отметка времени] для вывода [данных конфигурации]

  • Гарантия высокой доступности, высокой стабильности, высокой производительности, отказоустойчивости

Настроить данные для многоуровневого кэширования, кэш первого уровня [redis], кэш второго уровня [память сервера] (php apcu)
Интерфейс преимущественно получен из [памяти сервера].Если он не существует из [redis] и синхронизируется с [памятью сервера], он не существует из [mysql] и синхронизируется с [redis].После обычного фонового редактирования он будет быть синхронизированы с Redis, [память сервера] ] временно кэшируется (3 с), чтобы обеспечить его быструю доставку в случае высокого параллелизма. Недостаток заключается в том, что при изменении данных они будут обновляться с задержкой N/s.

Когда клиент получает конфигурацию кэша, если нет конфигурации по умолчанию, клиент не может получить механизм отказоустойчивости конфигурации в крайних случаях, чтобы обеспечить нормальную работу функции.

решение

Интерфейс списка управления конфигурацией:

配置管理

Конфигурация добавляет и формирует интерфейс конфигурации JSON (действие разработчика):

配置管理

Настройте интерфейс формы данных (детская обувь товар/операция):

配置管理

Фронтенд-фреймворки/библиотеки:

  • vuejs
  • element uiГолодный интерфейс
  • jsoneditorкомпонент редактирования json
  • VueQuillEditorкомпонент форматированного текста vuejs

Основное содержание кода выглядит следующим образом:

Дизайн стола:

-- 配置中心表
CREATE TABLE `config_center` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '标题',
  `code` varchar(60) NOT NULL DEFAULT '' COMMENT '标识',
  `platform` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0=所有,1=IOS,2=安卓',
  `template` tinyint(4) NOT NULL DEFAULT '1' COMMENT '模板标识',
  `form_json` text NOT NULL COMMENT '表单JSON',
  `form_data` text NOT NULL COMMENT '表单数据',
  `description` varchar(255) NOT NULL DEFAULT '' COMMENT '描述',
  `app_version` varchar(15) NOT NULL DEFAULT '' COMMENT 'app版本',
  `app_version_compare` varchar(10) NOT NULL DEFAULT '' COMMENT 'app版本比较符号',
  `operator` varchar(20) NOT NULL DEFAULT '' COMMENT '编辑人',
  `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态,1=有效,-1=删除',
  PRIMARY KEY (`id`),
  KEY `index_code` (`code`),
  KEY `index_update_at_platform` (`update_at`,`platform`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Конфигурация формы Содержимое JOSN:

[
    {
        el: "input",
        type: "textarea",
        name: "名字",
        field: "name",
        value: "6666",
        rule: [
            {
                required: true,
                message: "请输入活动名称",
                trigger: "blur"
            }
        ]
    },
    {
        el: "input-number",
        type: "",
        name: "数字",
        field: "number",
        value: 1,
        min:1,
        max:1000,
        rule: [
            {
                required: true,
                message: "数字",
                trigger: "blur"
            }
        ]
    },
    {
        el: "input",
        type: "text",
        name: "描述",
        field: "desc",
        value: "",
        rule: [
            {
                required: true,
                message: "请输入活动名称",
                trigger: "blur"
            }
        ]
    },
    {
        el: "editor",
        type: "",
        name: "富文本",
        field: "editor",
        value: "",
        rule: [
            {
                required: true,
                message: "请输入内容",
                trigger: "blur"
            }
        ]
    },
    {
        el: "date",
        type: "datetimerange",
        name: "日期范围",
        field: "datetime",
        value: ["2019-01-01 10:00:00", "2019-03-01 08:00:00"],
        rule: [
            {
                required: true,
                message: "必须",
                trigger: "blur"
            }
        ]
    },
    {
        el: "switch",
        type: "",
        name: "开关",
        field: "open",
        value: false,
        rule: [
            {
                required: true,
                message: "必须",
                trigger: "blur"
            }
        ]
    },
    {
        el: "date",
        type: "datetime",
        name: "活动时间",
        field: "datet",
        value: "2019-01-01"
    },
    {
        el: "slider",
        type: "",
        name: "范围",
        field: "fw",
        value: 0,
        max: 500
    },
    {
        el: "color",
        type: "",
        name: "颜色",
        field: "color",
        value: ""
    },
    {
        el: "radio",
        type: "",
        name: "类型",
        field: "type",
        value: 0,
        options: [
            {
                label: "类型1",
                value: 1
            },
            {
                label: "类型2",
                value: 2
            },
            {
                label: "类型3",
                value: 3
            }
        ]
    },
    {
        el: "select",
        type: "",
        name: "食品",
        field: "foods",
        value: "黄金糕",
        options: [
            {
                value: 1,
                label: "黄金糕"
            },
            {
                value: 2,
                label: "双皮奶"
            },
            {
                value: 3,
                label: "蚵仔煎"
            },
            {
                value: 4,
                label: "龙须面"
            },
            {
                value: 5,
                label: "北京烤鸭"
            }
        ]
    },
    {
        el: "checkbox",
        type: "",
        name: "城市",
        field: "city",
        value: [0],
        options: [
            {
                value: 1,
                label: "上海"
            },
            {
                value: 2,
                label: "深圳"
            },
            {
                value: 3,
                label: "北京"
            }
        ]
    }
];

основной код шаблона формы vuejs + element ui (простой и грубый)

<el-form size="small" :rules="rules" ref="form" :model="form" label-width="80px">
    <el-form-item v-for="(item,index) in formData" :key="item.key" :label="item.name" :prop="item.field">
        <!--input 输入框-->
        <el-input v-if="item.el==='input'" :type="item.type" style="width:400px" v-model="form[item.field]"></el-input>
    
        <!--input 数字输入框-->
        <el-input-number v-if="item.el==='input-number'" :min="item.min" :max="item.max" v-model="form[item.field]"></el-input-number>
    
        <!--datetime 时间-->
        <el-date-picker v-if="item.el==='date'" :type="item.type" v-model="form[item.field]" placeholder="选择日期时间">
        </el-date-picker>
    
        <!--switch 开关-->
        <el-switch v-if="item.el==='switch'" v-model="form[item.field]" active-text="" inactive-text="">
        </el-switch>
    
        <!--滑块-->
        <el-slider v-if="item.el==='slider'" v-model="form[item.field]" :max="item.max?item.max:100"></el-slider>
    
        <!--颜色选择-->
        <el-color-picker v-if="item.el==='color'" v-model="form[item.field]"></el-color-picker>
    
        <!--单选-->
        <el-radio v-if="item.el==='radio'" v-for="(option,index) in item.options" :key="option.key" v-model="form[item.field]" :label="option.value">
            {{ option.label }}
        </el-radio>
    
        <!--多选-->
        <el-checkbox-group v-if="item.el==='checkbox'" v-model="form[item.field]">
            <el-checkbox v-for="(option,index) in item.options" :key="option.value"  :label="option.value">
                {{ option.label }}
            </el-checkbox>
        </el-checkbox-group>
    
        <!--选择器-->
        <el-select v-if="item.el==='select'" v-model="form[item.field]" placeholder="请选择">
            <el-option v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value">
            </el-option>
        </el-select>
    
        <!-- 富文本-->
        <quill-editor v-if="item.el==='editor'" v-model="form[item.field]"></quill-editor>
    </el-form-item>                
</el-form>

js-код:


//富文本组件
Vue.use(VueQuillEditor);
$vm = new Vue({
    el: "#app",
    data: {
        template: "1",
        form: {},
        rules: {},
        formData: {},
    },
    methods: {
        useTemplate: function () {
            switch (this.template) {
                case "1": {
                    var formJson = [];
                    if (this.config['form_json']) {
                        formJson = this.config['form_json'];
                    } else if (templateOneJson) {
                        formJson = templateOneJson;
                    }
                    editorJson(formJson);
                    this.createForm(formJson);
                    return
                }
            }
        },
        //预览
        review: function () {
            var jsonData = editor.get();
            this.createForm(jsonData);
        },
        //根据配置的JSON,解析出构造表单需要的Vue数据
        getData: function (json) {
            var data = {
                //表单数据
                form: {},
                //表单验证规则
                rules: {},
                //表单控件配置
                formData: {}
            };
            //构造数据
            for (var index in json) {
                var item = json[index];
                data.form[item.field] = item.value;
                if (item.rule) data.rules[item.field] = item.rule;
            }
            data.formData = json;
            return data;
        },
        //创建表单Vue对象
        formVue: function (data) {
            Vue.set($vm, "form", data.form);
            Vue.set($vm, "rules", data.rules);
            Vue.set($vm, "formData", data.formData);
            // $vm.$forceUpdate();
        },
        //根据配置JSON生成Form表单
        createForm: function (json) {
            var data = this.getData(json);
            console.log(data);
            this.formVue(data);
        }
    }
});

Поскольку интерфейсная часть основана на технической базе исходного проекта, в ней используется самый примитивный метод введения ссылок, и в нем не участвуют фронтенд-студенты. фронт и бэк, а потом упаковать на основе компонентов, было бы лучше.Хорошо сохранить детскую обувь заднего конца и подумать об этом.Это немного низко, и его можно использовать, но это не влияет на основные идеи реализации и может быть использовано для справки.

Суммировать

Когда вы разрабатываете требования к продукту, помимо решения насущных проблем, задумывались ли вы о многих подобных проблемах до или в будущем? Расширение вашего решения от решения одной проблемы до решения класса проблем - очень важная способность и часто разделительная линия между новичками и старшими техническими специалистами.


Впервые опубликовано на Github🌈 Большой разговор о веб-разработке, добро пожаловать Звезда 🥰

Категории