Mr.Shi
2023-08-11 5a7fb4358eb902ce139096f20ef3c0625adcd7f4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<template>
  <GlobalWindow
    :title="title"
    :visible.sync="visible"
    :confirm-working="isWorking"
    width="40%"
    @confirm="confirm"
  >
    <el-form :model="form" ref="form" :rules="rules">
      <el-form-item label="任务名称" prop="jobName" required>
        <el-input v-model="form.jobName" placeholder="请输入任务名称" v-trim/>
      </el-form-item>
      <el-form-item label="任务描述" prop="jobDescription">
        <el-input v-model="form.jobDescription" type="textarea" placeholder="请输入JOB描述" v-trim/>
      </el-form-item>
      <el-form-item label="任务处理器类" prop="handler" required>
        <el-input v-model="form.handler" placeholder="请输入任务处理器类" v-trim/>
      </el-form-item>
      <el-form-item label="CRON表达式" prop="cronExpression" required>
        <el-input v-model="form.cronExpression" placeholder="请输入CRON表达式" v-trim/>
      </el-form-item>
      <el-form-item label="是否启用数据分片" prop="enableSnippet" class="form-item-switch" required>
        <el-switch v-model="form.enableSnippet"/>
        <span class="switch-text">{{form.enableSnippet | enableText}}</span>
        <FormItemTip>数据分片可将一个任务需处理的数据分成多个子任务来处理,以提高任务的业务处理速度。</FormItemTip>
      </el-form-item>
      <el-form-item v-if="form.enableSnippet" label="数据分发处理器类" prop="distributeHandler" required>
        <el-input v-model="form.distributeHandler" placeholder="请输入数据分发处理器类" v-trim/>
      </el-form-item>
      <el-form-item v-if="form.enableSnippet" label="子任务最大处理数据量" prop="distributeLimit" required>
        <el-input-number v-model="form.distributeLimit" placeholder="请输入子任务最大处理数据量" v-trim/>
        <FormItemTip>用于限制子任务处理数据量的最大能力</FormItemTip>
      </el-form-item>
      <el-form-item label="是否启用并发执行" prop="disallowConcurrent" class="form-item-switch" required>
        <el-switch v-model="form.disallowConcurrent" :active-value="false" :inactive-value="true"/>
        <span class="switch-text">{{form.disallowConcurrent | disabledText}}</span>
        <FormItemTip>同一任务在同一机器是否允许并发执行,关闭后将使用Quartz提供的@DisallowConcurrentExecution注解实现</FormItemTip>
      </el-form-item>
      <el-form-item label="是否启用异步执行" prop="withAsync" class="form-item-switch" required>
        <el-switch v-model="form.withAsync"/>
        <span class="switch-text">{{form.withAsync | enableText}}</span>
        <FormItemTip>启用后任务将通过创建分片的方式异步执行,提高服务器资源的利用率</FormItemTip>
      </el-form-item>
      <el-form-item label="是否启用日志" prop="withLog" class="form-item-switch" required>
        <el-switch v-model="form.withLog"/>
        <span class="switch-text">{{form.withLog | enableText}}</span>
        <FormItemTip>启用日志后,每次任务及其分片任务的执行都会被记录进任务日志中</FormItemTip>
      </el-form-item>
      <el-form-item label="服务器白名单" prop="allowServerIps">
        <el-input type="textarea" v-model="form.allowServerIps" placeholder="请输入服务器IP,多个IP使用英文逗号隔开"/>
        <FormItemTip>如希望当前任务仅在某(些)台服务器中执行,则可以在此填入服务器内网IP,为空时表示所有服务器均可执行。</FormItemTip>
      </el-form-item>
    </el-form>
  </GlobalWindow>
</template>
 
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalWindow from '@/components/common/GlobalWindow'
import FormItemTip from '@/components/common/FormItemTip'
export default {
  name: 'OperaJobWindow',
  extends: BaseOpera,
  components: { FormItemTip, GlobalWindow },
  data () {
    return {
      // 原数据
      originData: null,
      // 表单数据
      form: {
        id: null,
        jobName: '',
        jobDescription: '',
        handler: '',
        enableSnippet: false,
        distributeHandler: '',
        distributeLimit: null,
        disallowConcurrent: false,
        withAsync: true,
        withLog: true,
        cronExpression: '',
        allowServerIps: ''
      },
      // 验证规则
      rules: {
        jobName: [
          { required: true, message: '请输入任务名称' }
        ],
        handler: [
          { required: true, message: '请输入任务处理器类' }
        ],
        cronExpression: [
          { required: true, message: '请输入CRON表达式' }
        ],
        distributeHandler: [
          { required: true, message: '请输入数据分发处理器类' }
        ],
        allowServerIps: [
          { validator: this.__checkServerIps, trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    /**
     * 打开窗口
     *
     * @param title 标题
     * @param target 行对象(仅编辑需该参数)
     */
    open (title, target) {
      this.title = title
      this.visible = true
      // 新建
      if (target == null) {
        this.$nextTick(() => {
          this.$refs.form.resetFields()
          this.form[this.configData['field.id']] = null
        })
        return
      }
      // 编辑
      this.$nextTick(() => {
        for (const key in this.form) {
          this.form[key] = target[key]
        }
        this.form.enableSnippet = this.form.distributeHandler != null && this.form.distributeHandler.trim() !== ''
        this.originData = JSON.parse(JSON.stringify(this.form))
      })
    },
    /**
     * 确认新建
     *
     * @private
     */
    __confirmCreate () {
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return
        }
        // 调用新建接口
        this.isWorking = true
        this.api.create(this.form)
          .then(() => {
            this.visible = false
            this.$emit('success')
            setTimeout(() => {
              this.$dialog.attentionConfirm('新建成功,需重启服务后生效').then(() => {})
            }, 300)
          })
          .catch(e => {
            this.$tip.apiFailed(e)
          })
          .finally(() => {
            this.isWorking = false
          })
      })
    },
    /**
     * 确认修改
     *
     * @private
     */
    __confirmEdit () {
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return
        }
        // 调用更新接口
        this.isWorking = true
        this.api.updateById(this.form)
          .then(() => {
            this.visible = false
            this.$emit('success')
            // 如果修改了处理器、CRON表达式、分发器处理器
            const props = []
            if (this.originData.handler !== this.form.handler) {
              props.push('任务处理器类')
            }
            if (this.originData.cronExpression !== this.form.cronExpression) {
              props.push('CRON表达式')
            }
            if (this.originData.distributeHandler !== this.form.distributeHandler) {
              props.push('数据分发处理器类')
            }
            if (this.originData.disallowConcurrent !== this.form.disallowConcurrent) {
              props.push('是否启用并发执行')
            }
            if (props.length > 0) {
              setTimeout(() => {
                this.$dialog.attentionConfirm(`修改成功,由于您修改了${props.join('、')},任务配置需要重启服务后才可生效`).then(() => {})
              }, 300)
              return
            }
            this.$tip.apiSuccess('修改成功')
          })
          .catch(e => {
            this.$tip.apiFailed(e)
          })
          .finally(() => {
            this.isWorking = false
          })
      })
    },
    /**
     * 验证服务器白名单配置
     *
     * @param rule 规则
     * @param value 值
     * @param callback 回调
     * @private
     */
    __checkServerIps (rule, value, callback) {
      // 为空时不验证
      if (value == null || value === '') {
        return callback()
      }
      // 验证IP
      const ips = value.split(',')
      for (const ip of ips) {
        if (!/^[\d]{1,3}.[\d]{1,3}.[\d]{1,3}.[\d]{1,3}$/.test(ip)) {
          return callback(new Error('IP格式不正确,多个IP可使用","分割'))
        }
      }
      return callback()
    }
  },
  created () {
    this.config({
      api: '/system/job',
      'field.id': 'id'
    })
  }
}
</script>