github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/ui/src/components/FieldRange.vue (about)

     1  <template>
     2    <div class="panel">
     3      <a-form-model ref="editForm">
     4        <a-row :gutter="cols" class="title">
     5          <a-col :span="col">{{ $t('form.type') }}</a-col>
     6          <a-col :span="col">{{ $t('form.value') }}</a-col>
     7          <a-col :span="col">{{ $t('form.opt') }}</a-col>
     8        </a-row>
     9  
    10        <a-row v-if="!sections || sections.length == 0" :gutter="cols">
    11          <a-col :span="col"></a-col>
    12          <a-col :span="col"></a-col>
    13          <a-col :span="col">
    14            <a class="edit">
    15              <a @click="insertSection()" class="edit">{{ $t('action.add') }}</a>
    16            </a>
    17          </a-col>
    18        </a-row>
    19  
    20        <a-row v-for="item in sections" :key="item.id" :gutter="cols">
    21  
    22          <a-col :span="col">
    23            <span v-if="item.type=='interval'">{{ $t('form.type.interval') }}</span>
    24            <span v-if="item.type=='list'">{{ $t('form.type.list') }}</span>
    25            <span v-if="item.type=='literal'">{{ $t('form.type.literal') }}</span>
    26          </a-col>
    27  
    28          <a-col :span="col">
    29            <span>{{ item.value }}</span>
    30          </a-col>
    31  
    32          <a-col :span="8">
    33            <a class="edit">
    34              <a @click="insertSection(item)" class="edit">{{ $t('action.add') }}</a> &nbsp;
    35              <a @click="editSection(item)" class="edit">{{ $t('action.edit') }}</a> &nbsp;
    36              <a-popconfirm
    37                  :title="$t('tips.delete')"
    38                  :okText="$t('msg.yes')"
    39                  :cancelText="$t('msg.no')"
    40                  @confirm="removeSection(item)"
    41              >
    42                <a class="edit">{{ $t('action.delete') }}</a>
    43              </a-popconfirm>
    44            </a>
    45          </a-col>
    46        </a-row>
    47      </a-form-model>
    48  
    49      <a-modal
    50          :title="editTitle"
    51          :width="600"
    52          :visible="editSectionVisible"
    53          :okText="$t('form.save')"
    54          :cancelText="$t('form.cancel')"
    55          @ok="saveSection"
    56          @cancel="cancelSection">
    57        <div>
    58          <a-form-model ref="editForm" :model="section" :rules="rules">
    59  
    60            <a-row :gutter="cols">
    61              <a-col :span="cols">
    62                <a-form-model-item :label="$t('form.type')" prop="type" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
    63                  <a-select v-model="section.type">
    64                    <a-select-option value="interval">{{ $t('form.type.interval') }}</a-select-option>
    65                    <a-select-option value="list">{{ $t('form.type.list') }}</a-select-option>
    66                    <a-select-option value="literal">{{ $t('form.type.literal') }}</a-select-option>
    67                  </a-select>
    68                </a-form-model-item>
    69              </a-col>
    70            </a-row>
    71  
    72            <div v-if="section.type==='interval'">
    73              <a-row :gutter="cols">
    74                <a-col :span="cols">
    75                  <a-form-model-item :label="$t('form.start')" prop="start" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
    76                    <a-input v-model="section.start" :placeholder="$t('tips.number.or.letter')" />
    77                  </a-form-model-item>
    78                </a-col>
    79              </a-row>
    80              <a-row :gutter="cols">
    81                <a-col :span="cols">
    82                  <a-form-model-item :label="$t('form.end')" prop="end" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
    83                    <a-input v-model="section.end" :placeholder="$t('tips.number.or.letter')" />
    84                  </a-form-model-item>
    85                </a-col>
    86              </a-row>
    87              <a-row :gutter="cols">
    88                <a-col :span="cols">
    89                  <a-form-model-item :label="$t('form.repeat')" prop="repeat" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
    90                    <a-input v-model="section.repeat" :precision="0" :min="1" placeholder="" />
    91                  </a-form-model-item>
    92                </a-col>
    93              </a-row>
    94              <a-row :gutter="cols">
    95                <a-col :span="cols">
    96                  <a-form-model-item :label="$t('form.repeatTag')" prop="repeatTag" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
    97                    <a-radio-group v-model="section.repeatTag">
    98                      <a-radio :value="''">
    99                        {{ $t('form.repeatItem') }}
   100                      </a-radio>
   101                      <a-radio :value="'!'">
   102                        {{ $t('form.repeatGroup') }}
   103                      </a-radio>
   104                    </a-radio-group>
   105                  </a-form-model-item>
   106                </a-col>
   107              </a-row>
   108  
   109              <a-row :gutter="cols">
   110                <a-col :span="cols">
   111                  <a-form-model-item :label="$t('form.rand')" prop="rand" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
   112                    <a-switch v-model="section.rand" />
   113                  </a-form-model-item>
   114                </a-col>
   115              </a-row>
   116              <a-row :gutter="cols" v-if="!section.rand">
   117                <a-col :span="cols">
   118                  <a-form-model-item :label="$t('form.step')" prop="step" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
   119                    <a-input v-model="section.step" :placeholder="$t('tips.number')" />
   120                  </a-form-model-item>
   121                </a-col>
   122              </a-row>
   123            </div>
   124  
   125            <div v-if="section.type==='list'">
   126              <a-row :gutter="cols">
   127                <a-col :span="cols">
   128                  <a-form-model-item :label="$t('form.type.list')" prop="text" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
   129                    <a-input v-model="section.text" type="textarea" rows="3" />
   130                    {{$t('tips.value.each.line')}}
   131                  </a-form-model-item>
   132                </a-col>
   133              </a-row>
   134            </div>
   135  
   136            <div v-if="section.type==='literal'">
   137              <a-row :gutter="cols">
   138                <a-col :span="cols">
   139                  <a-form-model-item label="常量" prop="text" :labelCol="labelColFull" :wrapperCol="wrapperColFull">
   140                    <a-input v-model="section.text" placeholder="" />
   141                  </a-form-model-item>
   142                </a-col>
   143              </a-row>
   144            </div>
   145          </a-form-model>
   146  
   147        </div>
   148  
   149      </a-modal>
   150  
   151    </div>
   152  </template>
   153  
   154  <script>
   155  import {
   156    listSection, createSection, removeSection, updateSection,
   157  } from "../api/section";
   158  import {sectionStrToArr, trimChar} from "../api/utils";
   159  
   160  export default {
   161    name: 'FieldRangeComponent',
   162    data() {
   163      return {
   164        cols: 24,
   165        colsHalf: 12,
   166        col: 8,
   167        labelColFull: { lg: { span: 4 }, sm: { span: 4 } },
   168        labelColHalf: { lg: { span: 8}, sm: { span: 8 } },
   169        wrapperColFull: { lg: { span: 16 }, sm: { span: 16 } },
   170        wrapperColHalf: { lg: { span: 12 }, sm: { span: 12 } },
   171  
   172        sections: [],
   173        section: {},
   174        editTitle: '',
   175        editSectionVisible: false,
   176  
   177        rules: {
   178          type: [
   179            { required: true, message: this.$i18n.t('valid.type.empty'), trigger: 'change' },
   180          ],
   181          start: [
   182            { required: true, message: this.$i18n.t('valid.number.or.single.letter'), trigger: 'change' },
   183            { validator: this.checkRange, trigger: 'change' },
   184          ],
   185          end: [
   186            { required: true, message: this.$i18n.t('valid.number.or.single.letter'), trigger: 'change' },
   187            { validator: this.checkRange, trigger: 'change' },
   188          ],
   189          repeat: [
   190            { validator: this.checkRepeat, message: this.$i18n.t('valid.unsigned.integer'), trigger: 'change' },
   191          ],
   192          step: [
   193            { validator: this.checkStep, message: this.$i18n.t('valid.number'), trigger: 'change' },
   194          ],
   195        },
   196      };
   197    },
   198    props: {
   199      type: {
   200        type: String,
   201        default: () => ''
   202      },
   203      model: {
   204        type: Object,
   205        default: () => null
   206      },
   207      time2: {
   208        type: Number,
   209        default: () => 0
   210      },
   211    },
   212  
   213    computed: {
   214    },
   215    created () {
   216      console.log('created')
   217  
   218      this.loadData()
   219      this.$watch('time2', () => {
   220        console.log('time2 changed', this.time2)
   221        this.loadData()
   222      })
   223    },
   224    mounted () {
   225      console.log('mounted')
   226    },
   227    methods: {
   228      loadData () {
   229        console.log('loadData', this.type, this.model)
   230        if (!this.model.id) return
   231  
   232        listSection(this.model.id, this.type).then(res => {
   233          console.log('listSection', res)
   234          this.sections = res.data
   235        })
   236      },
   237      insertSection (item) {
   238        createSection(this.model.id, item ? item.id : 0, this.type).then(res => {
   239          console.log('createSection', res)
   240          this.sections = res.data
   241        })
   242      },
   243  
   244      editSection (item) {
   245        console.log('editSection', item)
   246  
   247        if (item.type === 'interval') {
   248          this.editTitle = '编辑范围'
   249        } else if (item.type === 'literal') {
   250          this.editTitle = '编辑字面常量'
   251          item.text = trimChar(item.value, '`')
   252        } else if (item.type === 'list') {
   253          this.editTitle = '编辑数组'
   254          item.text = item.value
   255          item.text = sectionStrToArr(item.value)
   256        }
   257  
   258        this.section = item
   259        this.editSectionVisible = true
   260      },
   261      saveSection() {
   262        this.$refs.editForm.validate(valid => {
   263          console.log(valid, this.section)
   264          if (!valid) {
   265            console.log('validation fail')
   266            return
   267          }
   268  
   269          if (this.section.type === 'interval') {
   270            this.section.value = this.section.start + '-' + this.section.end
   271  
   272            if (this.section.rand) {
   273              this.section.value += ':R'
   274              this.section.step = 0
   275            } else if (this.section.step && this.section.step != '' && this.section.step != 1) {
   276              const regx = /^[a-z,A-Z]$/
   277              if (regx.test(this.section.start) || regx.test(this.section.end)) {
   278                this.section.step = Math.floor(this.section.step)
   279              }
   280  
   281              this.section.value += ':' + this.section.step
   282            }
   283  
   284            if (this.section.repeat && this.section.repeat != '' && this.section.repeat != '1') {
   285              this.section.value += '{' + this.section.repeat + this.section.repeatTag + '}'
   286            }
   287  
   288          } else if (this.section.type === 'literal') {
   289            this.section.value = '`' + this.section.text + '`'
   290  
   291          } else if (this.section.type === 'list') {
   292            const arr = this.section.text.split('\n')
   293            this.section.value = '[' + arr.join(',') + ']'
   294          }
   295  
   296          this.section.step = parseInt(this.section.step)
   297          updateSection(this.section, this.type).then(res => {
   298            console.log('updateSection', res)
   299            this.sections = res.data
   300          })
   301  
   302          this.editSectionVisible = false
   303        })
   304      },
   305      cancelSection() {
   306        console.log('cancelSection')
   307        this.editSectionVisible = false
   308      },
   309  
   310      removeSection (item) {
   311        console.log(item)
   312        removeSection(item.id, this.type).then(res => {
   313          console.log('removeSection', res)
   314          this.sections = res.data
   315        })
   316      },
   317      checkRange (rule, value, callback){
   318        console.log('checkRange', value)
   319  
   320        const test1 = /^[0-9]+\.?[0-9]*$/.test(value);
   321        const test2 = /^[a-z,A-Z]$/.test(value);
   322        if (!test1 && !test2) {
   323          callback('必须是数字或单个字母')
   324        }
   325  
   326        callback()
   327      },
   328      checkRepeat(rule, value, callback) {
   329        const test = /^[1-9][0-9]*$/.test(value);
   330        if (!test) {
   331          callback('必须是正整数')
   332        }
   333        callback()
   334      },
   335      checkStep(rule, value, callback) {
   336        const test = /^[0-9]+\.?[0-9]*$/.test(value);
   337        if (!test) {
   338          callback('必须是数字')
   339        }
   340        callback()
   341      }
   342    }
   343  }
   344  </script>
   345  
   346  <style lang="less" scoped>
   347  .panel {
   348    padding: 4px 8px;
   349    .title {
   350      font-weight: bolder;
   351      margin-bottom: 5px;
   352      padding-bottom: 5px;
   353      border-bottom: 1px solid #e9f2fb;
   354    }
   355    .radios {
   356      margin-bottom: 12px;
   357      .range {
   358        display: inline-block;
   359        margin-left: 12px;
   360      }
   361    }
   362    .edit {
   363      line-height: 32px;
   364    }
   365  }
   366  </style>