655 lines
20 KiB
Vue
655 lines
20 KiB
Vue
<template>
|
|
<de-layout-content :header="header" backPath="/system/system-task/dataset">
|
|
<div class="dataset-editer-form">
|
|
<div class="w600">
|
|
<el-form
|
|
ref="taskForm"
|
|
:form="taskForm"
|
|
:model="taskForm"
|
|
:disabled="disableForm"
|
|
label-width="100px"
|
|
class="de-form-item"
|
|
:rules="taskFormRules"
|
|
>
|
|
<el-form-item
|
|
@click.native="selectDataset"
|
|
:label="$t('chart.select_dataset')"
|
|
prop="datasetName"
|
|
>
|
|
<el-input
|
|
v-model="taskForm.datasetName"
|
|
size="small"
|
|
readonly
|
|
:placeholder="$t('dataset.task_name')"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item :label="$t('dataset.task_name')" prop="name">
|
|
<el-input
|
|
v-model="taskForm.name"
|
|
size="small"
|
|
:placeholder="$t('dataset.task_name')"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item :label="$t('dataset.update_type')" prop="type">
|
|
<el-radio-group v-model="taskForm.type">
|
|
<el-radio label="all_scope">{{
|
|
$t("dataset.all_scope")
|
|
}}</el-radio>
|
|
<el-radio label="add_scope">
|
|
{{ $t("dataset.add_scope") }}</el-radio
|
|
>
|
|
</el-radio-group>
|
|
</el-form-item>
|
|
<div class="add-scope-cont" v-if="taskForm.type === 'add_scope'">
|
|
<el-form-item
|
|
prop="incrementalUpdateType"
|
|
:label="$t('dataset.incremental_update_type')"
|
|
>
|
|
<el-radio-group
|
|
v-model="incrementalUpdateType"
|
|
size="small"
|
|
@change="incrementalUpdateTypeChange"
|
|
>
|
|
<el-radio label="incrementalAdd">{{
|
|
$t("dataset.incremental_add")
|
|
}}</el-radio>
|
|
<el-radio label="incrementalDelete">{{
|
|
$t("dataset.incremental_delete")
|
|
}}</el-radio>
|
|
</el-radio-group>
|
|
<div class="param-title">
|
|
<span>{{ $t("dataset.param") }}</span>
|
|
<div class="param-title-btn">
|
|
<el-button
|
|
type="text"
|
|
size="small"
|
|
@click="insertParamToCodeMirror('${__last_update_time__}')"
|
|
>{{ $t("dataset.last_update_time") }}</el-button
|
|
>
|
|
<el-button
|
|
type="text"
|
|
size="small"
|
|
@click="
|
|
insertParamToCodeMirror('${__current_update_time__}')
|
|
"
|
|
>{{ $t("dataset.current_update_time") }}</el-button
|
|
>
|
|
</div>
|
|
</div>
|
|
<div class="codemirror-cont">
|
|
<codemirror
|
|
ref="myCm"
|
|
v-model="sql"
|
|
class="codemirror"
|
|
:options="sqlOption"
|
|
@ready="onCmReady"
|
|
@focus="onCmFocus"
|
|
@input="onCmCodeChange"
|
|
/>
|
|
</div>
|
|
</el-form-item>
|
|
</div>
|
|
|
|
<el-form-item :label="$t('dataset.execute_rate')" prop="rate">
|
|
<el-radio-group v-model="taskForm.rate" @change="onRateChange">
|
|
<el-radio label="SIMPLE">{{
|
|
$t("dataset.execute_once")
|
|
}}</el-radio>
|
|
<el-radio label="CRON">{{ $t("dataset.cron_config") }}</el-radio>
|
|
<el-radio label="SIMPLE_CRON">{{
|
|
$t("dataset.simple_cron")
|
|
}}</el-radio>
|
|
</el-radio-group>
|
|
</el-form-item>
|
|
<div class="execute-rate-cont" v-if="taskForm.rate !== 'SIMPLE'">
|
|
<el-form-item
|
|
v-if="taskForm.rate === 'SIMPLE_CRON'"
|
|
:label="$t('dataset.execute_rate')"
|
|
prop="rate"
|
|
>
|
|
<div class="simple-cron">
|
|
{{ $t("cron.every") }}
|
|
<el-input-number
|
|
v-model="taskForm.extraData.simple_cron_value"
|
|
controls-position="right"
|
|
:min="1"
|
|
size="small"
|
|
></el-input-number>
|
|
<el-select
|
|
v-model="taskForm.extraData.simple_cron_type"
|
|
filterable
|
|
size="small"
|
|
@change="onSimpleCronChange()"
|
|
>
|
|
<el-option :label="$t('components.minute')" value="minute" />
|
|
<el-option :label="$t('components.hour')" value="hour" />
|
|
<el-option :label="$t('components.day')" value="day" />
|
|
</el-select>
|
|
{{ $t("cron.every_exec") }}
|
|
</div>
|
|
</el-form-item>
|
|
<el-form-item
|
|
prop="cron"
|
|
v-if="taskForm.rate === 'CRON' && showCron"
|
|
:label="$t('emailtask.cron_exp')"
|
|
>
|
|
<el-popover v-model="cronEdit">
|
|
<cron
|
|
:isRate="taskForm.rate === 'CRON'"
|
|
v-model="taskForm.cron"
|
|
@close="cronEdit = false"
|
|
/>
|
|
<el-input
|
|
slot="reference"
|
|
v-model="taskForm.cron"
|
|
size="small"
|
|
style="width: 50%"
|
|
@click="cronEdit = true"
|
|
/>
|
|
</el-popover>
|
|
</el-form-item>
|
|
<el-form-item
|
|
v-if="taskForm.rate !== 'SIMPLE'"
|
|
:label="$t('dataset.start_time')"
|
|
prop="startTime"
|
|
>
|
|
<el-date-picker
|
|
v-model="taskForm.startTime"
|
|
class="de-date-picker"
|
|
type="datetime"
|
|
:placeholder="$t('dataset.start_time')"
|
|
size="small"
|
|
>
|
|
</el-date-picker>
|
|
<svg-icon icon-class="icon_calendar_outlined" class="icon-calendar-outlined" />
|
|
</el-form-item>
|
|
<el-form-item
|
|
v-if="taskForm.rate !== 'SIMPLE'"
|
|
:label="$t('dataset.end_time')"
|
|
prop="end"
|
|
>
|
|
<el-radio-group v-model="taskForm.end">
|
|
<el-radio label="0">{{ $t("dataset.no_limit") }}</el-radio>
|
|
<el-radio label="1"> {{ $t("dataset.set_end_time") }}</el-radio>
|
|
</el-radio-group>
|
|
<el-date-picker
|
|
v-if="taskForm.end === '1'"
|
|
v-model="taskForm.endTime"
|
|
class="de-date-picker"
|
|
type="datetime"
|
|
:placeholder="$t('dataset.end_time')"
|
|
size="small"
|
|
/>
|
|
<svg-icon v-if="taskForm.end === '1'" icon-class="icon_calendar_outlined" class="icon-calendar-outlined" />
|
|
</el-form-item>
|
|
</div>
|
|
</el-form>
|
|
<table-selector
|
|
ref="tableSelector"
|
|
previewForTask="true"
|
|
privileges="manage"
|
|
@getTableId="getTableId"
|
|
:mode="1"
|
|
:clear-empty-dir="true"
|
|
:custom-type="['db', 'sql', 'api']"
|
|
show-mode="datasetTask"
|
|
/>
|
|
</div>
|
|
<div v-if="!disableForm" class="de-foot-layout">
|
|
<div class="cont">
|
|
<deBtn secondary @click="closeTask">{{ $t("dataset.cancel") }}</deBtn>
|
|
<deBtn type="primary" @click="saveTask(taskForm)">{{
|
|
$t("dataset.confirm")
|
|
}}</deBtn>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</de-layout-content>
|
|
</template>
|
|
|
|
<script>
|
|
import { post } from "@/api/dataset/dataset";
|
|
import DeLayoutContent from "@/components/business/DeLayoutContent";
|
|
import { hasDataPermission } from "@/utils/permission";
|
|
import msgCfm from "@/components/msgCfm/index";
|
|
|
|
import cron from "@/components/cron/cron";
|
|
import { codemirror } from "vue-codemirror";
|
|
import "codemirror/lib/codemirror.css";
|
|
import "codemirror/theme/eclipse.css";
|
|
import "codemirror/mode/sql/sql.js";
|
|
import "codemirror/addon/selection/active-line.js";
|
|
import "codemirror/addon/edit/closebrackets.js";
|
|
import "codemirror/mode/clike/clike.js";
|
|
import "codemirror/addon/edit/matchbrackets.js";
|
|
import "codemirror/addon/comment/comment.js";
|
|
import "codemirror/addon/dialog/dialog.js";
|
|
import "codemirror/addon/dialog/dialog.css";
|
|
import "codemirror/addon/search/searchcursor.js";
|
|
import "codemirror/addon/search/search.js";
|
|
import "codemirror/keymap/emacs.js";
|
|
import "codemirror/addon/hint/show-hint.css";
|
|
import "codemirror/addon/hint/sql-hint";
|
|
import "codemirror/addon/hint/show-hint";
|
|
import TableSelector from "./TableSelector";
|
|
|
|
export default {
|
|
components: { cron, codemirror, TableSelector, DeLayoutContent },
|
|
mixins: [msgCfm],
|
|
data() {
|
|
return {
|
|
disableForm: false,
|
|
table: {
|
|
name: "",
|
|
id: "",
|
|
},
|
|
showCron: false,
|
|
taskForm: {
|
|
name: "",
|
|
type: "all_scope",
|
|
startTime: "",
|
|
tableId: "",
|
|
rate: "SIMPLE",
|
|
cron: "",
|
|
endTime: "",
|
|
end: "0",
|
|
extraData: {
|
|
simple_cron_type: "hour",
|
|
simple_cron_value: 1,
|
|
},
|
|
},
|
|
taskFormRules: {
|
|
name: [
|
|
{
|
|
required: true,
|
|
message: this.$t("dataset.required"),
|
|
trigger: "change",
|
|
},
|
|
{
|
|
min: 2,
|
|
max: 50,
|
|
message: this.$t("datasource.input_limit_2_50", [2, 50]),
|
|
trigger: "blur",
|
|
},
|
|
],
|
|
type: [
|
|
{
|
|
required: true,
|
|
message: this.$t("dataset.required"),
|
|
trigger: "change",
|
|
},
|
|
],
|
|
startTime: [
|
|
{
|
|
required: true,
|
|
message: this.$t("components.time_is_required"),
|
|
trigger: "change",
|
|
},
|
|
],
|
|
rate: [
|
|
{
|
|
required: true,
|
|
message: this.$t("dataset.required"),
|
|
trigger: "change",
|
|
},
|
|
],
|
|
end: [
|
|
{
|
|
required: true,
|
|
message: this.$t("dataset.required"),
|
|
trigger: "change",
|
|
},
|
|
],
|
|
cron: [
|
|
{
|
|
required: true,
|
|
message: this.$t("dataset.required"),
|
|
trigger: "change",
|
|
},
|
|
],
|
|
datasetName: [
|
|
{
|
|
required: true,
|
|
message: this.$t("components.data_set_required"),
|
|
trigger: "change",
|
|
},
|
|
],
|
|
incrementalUpdateType: [
|
|
{
|
|
required: true,
|
|
trigger: "change",
|
|
},
|
|
],
|
|
},
|
|
cronEdit: false,
|
|
sqlOption: {
|
|
tabSize: 2,
|
|
styleActiveLine: true,
|
|
lineNumbers: true,
|
|
line: true,
|
|
mode: "text/x-sql",
|
|
theme: "eclipse",
|
|
hintOptions: {
|
|
// 自定义提示选项
|
|
completeSingle: false, // 当匹配只有一项的时候是否自动补全
|
|
},
|
|
},
|
|
incrementalConfig: {},
|
|
sql: "",
|
|
incrementalUpdateType: "incrementalAdd",
|
|
};
|
|
},
|
|
computed: {
|
|
header() {
|
|
return this.disableForm
|
|
? "查看任务"
|
|
: this.taskDetail.id
|
|
? "编辑任务"
|
|
: "添加任务";
|
|
},
|
|
},
|
|
created() {
|
|
const { datasetName, id } = this.$route.query;
|
|
this.taskDetail = { datasetName, id };
|
|
if (!id) {
|
|
this.taskForm.startTime = new Date()
|
|
return;
|
|
};
|
|
this.getTaskDetail(id);
|
|
},
|
|
methods: {
|
|
getTaskDetail(id) {
|
|
post(`/dataset/task/detail/${id}`, {}).then((res) => {
|
|
if (res.data.extraData) {
|
|
res.data.extraData = JSON.parse(res.data.extraData);
|
|
}
|
|
this.taskForm = res.data;
|
|
this.disableForm = this.disableEdit();
|
|
});
|
|
},
|
|
selectDataset() {
|
|
if (this.taskForm.id) return;
|
|
this.$refs.tableSelector.init();
|
|
},
|
|
getTableId(id, name) {
|
|
this.taskForm.tableId = id;
|
|
this.$set(this.taskForm, "datasetName", name);
|
|
},
|
|
onRateChange() {
|
|
if (this.taskForm.rate === "SIMPLE") {
|
|
this.taskForm.end = "0";
|
|
this.taskForm.endTime = "";
|
|
this.taskForm.cron = "";
|
|
this.showCron = false;
|
|
}
|
|
if (this.taskForm.rate === "SIMPLE_CRON") {
|
|
this.taskForm.cron = "0 0 0/1 * * ? *";
|
|
this.showCron = false;
|
|
}
|
|
if (this.taskForm.rate === "CRON") {
|
|
this.taskForm.cron = "00 00 * ? * * *";
|
|
this.$nextTick(() => {
|
|
this.showCron = true;
|
|
});
|
|
}
|
|
},
|
|
disableEdit() {
|
|
const { privileges, rate, status } = this.taskForm;
|
|
return (
|
|
rate === "SIMPLE" ||
|
|
status === "Stopped" ||
|
|
!hasDataPermission("manage", privileges)
|
|
);
|
|
},
|
|
onCmReady(cm) {
|
|
// this.codemirror.setSize("-webkit-fill-available", "auto");
|
|
},
|
|
onCmFocus(cm) {},
|
|
onCmCodeChange(newCode) {
|
|
this.sql = newCode;
|
|
this.$emit("codeChange", this.sql);
|
|
},
|
|
closeTask() {
|
|
this.$router.back();
|
|
},
|
|
onSimpleCronChange() {
|
|
if (this.taskForm.extraData.simple_cron_type === "minute") {
|
|
if (
|
|
this.taskForm.extraData.simple_cron_value < 1 ||
|
|
this.taskForm.extraData.simple_cron_value > 59
|
|
) {
|
|
this.$message({
|
|
message: this.$t("cron.minute_limit"),
|
|
type: "warning",
|
|
showClose: true,
|
|
});
|
|
this.taskForm.extraData.simple_cron_value = 59;
|
|
}
|
|
this.taskForm.cron =
|
|
"0 0/" + this.taskForm.extraData.simple_cron_value + " * * * ? *";
|
|
return;
|
|
}
|
|
if (this.taskForm.extraData.simple_cron_type === "hour") {
|
|
if (
|
|
this.taskForm.extraData.simple_cron_value < 1 ||
|
|
this.taskForm.extraData.simple_cron_value > 23
|
|
) {
|
|
this.$message({
|
|
message: this.$t("cron.hour_limit"),
|
|
type: "warning",
|
|
showClose: true,
|
|
});
|
|
this.taskForm.extraData.simple_cron_value = 23;
|
|
}
|
|
this.taskForm.cron =
|
|
"0 0 0/" + this.taskForm.extraData.simple_cron_value + " * * ? *";
|
|
return;
|
|
}
|
|
if (this.taskForm.extraData.simple_cron_type === "day") {
|
|
if (
|
|
this.taskForm.extraData.simple_cron_value < 1 ||
|
|
this.taskForm.extraData.simple_cron_value > 31
|
|
) {
|
|
this.$message({
|
|
message: this.$t("cron.day_limit"),
|
|
type: "warning",
|
|
showClose: true,
|
|
});
|
|
this.taskForm.extraData.simple_cron_value = 31;
|
|
}
|
|
this.taskForm.cron =
|
|
"0 0 0 1/" + this.taskForm.extraData.simple_cron_value + " * ? *";
|
|
return;
|
|
}
|
|
},
|
|
insertParamToCodeMirror(param) {
|
|
const pos1 = this.$refs.myCm.codemirror.getCursor();
|
|
const pos2 = {};
|
|
pos2.line = pos1.line;
|
|
pos2.ch = pos1.ch;
|
|
this.$refs.myCm.codemirror.replaceRange(param, pos2);
|
|
},
|
|
saveTask(task) {
|
|
this.$refs.taskForm.validate((valid) => {
|
|
if (valid) {
|
|
if (task.rate !== "SIMPLE") {
|
|
if (this.incrementalUpdateType === "incrementalAdd") {
|
|
this.incrementalConfig.incrementalAdd = this.sql;
|
|
} else {
|
|
this.incrementalConfig.incrementalDelete = this.sql;
|
|
}
|
|
this.incrementalConfig.tableId = task.tableId;
|
|
}
|
|
task.startTime = new Date(task.startTime).getTime();
|
|
task.endTime = new Date(task.endTime).getTime();
|
|
const form = JSON.parse(JSON.stringify(task));
|
|
form.extraData = JSON.stringify(form.extraData);
|
|
const dataSetTaskRequest = {
|
|
datasetTableTask: form,
|
|
datasetTableIncrementalConfig:
|
|
task.type === "add_scope" ? this.incrementalConfig : undefined,
|
|
};
|
|
post("/dataset/task/save", dataSetTaskRequest).then((response) => {
|
|
this.openMessageSuccess("dataset.save_success");
|
|
this.closeTask();
|
|
});
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
},
|
|
getIncrementalConfig(tableId) {
|
|
post("/dataset/table/incrementalConfig", { tableId: tableId }).then(
|
|
(response) => {
|
|
this.incrementalConfig = response.data;
|
|
|
|
if (
|
|
this.incrementalConfig.incrementalAdd.length === 0 &&
|
|
this.incrementalConfig.incrementalDelete.length === 0
|
|
) {
|
|
this.incrementalUpdateType = "incrementalAdd";
|
|
this.sql = "";
|
|
return;
|
|
}
|
|
if (this.incrementalConfig.incrementalAdd.length > 0) {
|
|
this.incrementalUpdateType = "incrementalAdd";
|
|
this.sql = this.incrementalConfig.incrementalAdd;
|
|
} else {
|
|
this.incrementalUpdateType = "incrementalDelete";
|
|
this.sql = this.incrementalConfig.incrementalDelete;
|
|
}
|
|
}
|
|
);
|
|
},
|
|
incrementalUpdateTypeChange: function () {
|
|
if (this.incrementalUpdateType === "incrementalAdd") {
|
|
if (this.sql) {
|
|
this.incrementalConfig.incrementalDelete = this.sql;
|
|
} else {
|
|
this.incrementalConfig.incrementalDelete = "";
|
|
}
|
|
if (this.incrementalConfig.incrementalAdd) {
|
|
this.sql = this.incrementalConfig.incrementalAdd;
|
|
} else {
|
|
this.sql = "";
|
|
}
|
|
}
|
|
|
|
if (this.incrementalUpdateType === "incrementalDelete") {
|
|
if (this.sql) {
|
|
this.incrementalConfig.incrementalAdd = this.sql;
|
|
} else {
|
|
this.incrementalConfig.incrementalAdd = "";
|
|
}
|
|
if (this.incrementalConfig.incrementalDelete) {
|
|
this.sql = this.incrementalConfig.incrementalDelete;
|
|
} else {
|
|
this.sql = "";
|
|
}
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.dataset-editer-form {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
.w600 {
|
|
width: 600px;
|
|
padding-top: 24px;
|
|
padding-bottom: 24px;
|
|
.el-radio:not(:last-child) {
|
|
margin-right: 0;
|
|
width: 156px;
|
|
}
|
|
|
|
.simple-cron {
|
|
display: flex;
|
|
align-items: center;
|
|
width: 100%;
|
|
.el-input-number,
|
|
.el-select {
|
|
width: 140px;
|
|
margin-left: 8px;
|
|
|
|
.el-input__inner {
|
|
text-align: left;
|
|
}
|
|
}
|
|
|
|
.el-select {
|
|
margin-right: 8px;
|
|
}
|
|
}
|
|
|
|
.execute-rate-cont {
|
|
box-sizing: border-box;
|
|
padding: 20px;
|
|
width: 100%;
|
|
background-color: var(--MainBG, #f5f6f7);
|
|
border-radius: 4px;
|
|
|
|
.el-input__inner {
|
|
background: var(--ContentBG, #ffffff) !important;
|
|
}
|
|
|
|
.el-date-editor {
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
.add-scope-cont {
|
|
height: 350px;
|
|
width: 100%;
|
|
border-radius: 4px;
|
|
padding: 20px;
|
|
background-color: var(--MainBG, #f5f6f7);
|
|
|
|
.param-title {
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding-bottom: 9px;
|
|
&:nth-child(1) {
|
|
font-family: PingFang SC;
|
|
font-size: 14px;
|
|
font-weight: 400;
|
|
color: var(--deTextPrimary, #1f2329);
|
|
}
|
|
}
|
|
|
|
.codemirror-cont {
|
|
box-sizing: border-box;
|
|
width: 560px;
|
|
height: 200px;
|
|
background: #ffffff;
|
|
border: 1px solid #bbbfc4;
|
|
border-radius: 4px;
|
|
overflow: auto;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.de-foot-layout {
|
|
position: absolute;
|
|
width: calc(100% - 48px);
|
|
height: 80px;
|
|
bottom: 0;
|
|
right: 24px;
|
|
background-color: var(--MainBG, #fff);
|
|
box-shadow: 0px -2px 4px rgba(0, 0, 0, 0.08);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 10;
|
|
.cont {
|
|
width: 600px;
|
|
text-align: right;
|
|
}
|
|
}
|
|
</style>
|