xiongzhu 2 лет назад
Родитель
Сommit
07d13c8fe4
4 измененных файлов с 235 добавлено и 115 удалено
  1. 1 0
      package.json
  2. 221 0
      src/views/CreateTask.vue
  3. 8 115
      src/views/HomeView.vue
  4. 5 0
      yarn.lock

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
     "qs": "^6.11.1",
     "resolve-url": "^0.2.1",
     "vue": "^3.2.47",
+    "vue-draggable-plus": "^0.2.1",
     "vue-router": "^4.1.6",
     "web3": "^4.0.1"
   },

+ 221 - 0
src/views/CreateTask.vue

@@ -0,0 +1,221 @@
+<template>
+    <ElConfigProvider size="small">
+        <ElDialog
+            class="create-task"
+            :model-value="modelValue"
+            title="新建任务"
+            width="800px"
+            :close-on-press-escape="false"
+            :close-on-click-modal="false"
+            @close="onClose"
+        >
+            <VueDraggable handle=".drag-icon" ref="el" v-model="items">
+                <ElCard v-for="(item, i) in items" :key="item.id" shadow="never" class="mb-4">
+                    <ElForm :model="item" :rules="rules" inline ref="form" class="flex items-center">
+                        <ElFormItem>
+                            <ElIcon class="drag-icon cursor-move" size="large">
+                                <ArrowsDownUp />
+                            </ElIcon>
+                        </ElFormItem>
+                        <ElFormItem prop="type">
+                            <ElSelect v-model="item.type">
+                                <ElOption v-for="key in TaskType" :key="key" :label="TaskType[key]" :value="key" />
+                            </ElSelect>
+                        </ElFormItem>
+                        <ElFormItem prop="amountType">
+                            <ElRadioGroup v-model="item.amountType">
+                                <ElRadio label="amount">随机金额</ElRadio>
+                                <ElRadio label="percent">随机百分比</ElRadio>
+                            </ElRadioGroup>
+                        </ElFormItem>
+                        <ElFormItem prop="amount" v-if="item.amountType === 'amount'">
+                            <ElInputNumber
+                                :controls="false"
+                                v-model="item.amount.min"
+                                class="!w-24"
+                                placeholder="最小金额"
+                            >
+                            </ElInputNumber>
+                            <div class="pl-2 pr-2">-</div>
+                            <ElInputNumber
+                                :controls="false"
+                                v-model="item.amount.max"
+                                class="!w-24"
+                                placeholder="最大金额"
+                            >
+                            </ElInputNumber>
+                        </ElFormItem>
+                        <ElFormItem prop="percent" v-else>
+                            <ElInputNumber
+                                :controls="false"
+                                v-model="item.percent.min"
+                                class="!w-24"
+                                placeholder="最小百分比"
+                                :min="1"
+                                :max="100"
+                            >
+                            </ElInputNumber>
+                            <div class="pl-2 pr-2">-</div>
+                            <ElInputNumber
+                                :controls="false"
+                                v-model="item.percent.max"
+                                class="!w-24"
+                                placeholder="最大百分比"
+                                :min="1"
+                                :max="100"
+                            >
+                            </ElInputNumber>
+                        </ElFormItem>
+                        <div class="flex-1"></div>
+                        <ElFormItem class="">
+                            <ElButton :icon="TrashX" type="danger" @click="removeItem(i)">删除</ElButton>
+                        </ElFormItem>
+                    </ElForm>
+                </ElCard>
+            </VueDraggable>
+
+            <ElButton @click="addItem">添加</ElButton>
+            <div class="text-xs mt-4 flex items-center">
+                <div class="mr-2">随机延迟</div>
+                <ElInputNumber
+                    :controls="false"
+                    v-model="delay.min"
+                    class="!w-24"
+                    placeholder="最小"
+                    :min="1"
+                    :max="100"
+                >
+                </ElInputNumber>
+                <div class="pl-2 pr-2">-</div>
+                <ElInputNumber
+                    :controls="false"
+                    v-model="delay.max"
+                    class="!w-24"
+                    placeholder="最大"
+                    :min="1"
+                    :max="100"
+                >
+                </ElInputNumber>
+                <div class="ml-2">秒</div>
+            </div>
+            <template #footer>
+                <ElButton @click="onClose">取消</ElButton>
+                <ElButton type="primary" @click="createTask" :loading="creatingTask">确定</ElButton>
+            </template>
+        </ElDialog>
+    </ElConfigProvider>
+</template>
+<script setup>
+import { ref } from 'vue'
+import { TaskType } from '@/enums'
+import { TrashX, ArrowsDownUp, Menu2 } from '@vicons/tabler'
+import { VueDraggable } from 'vue-draggable-plus'
+import { ElMessage } from 'element-plus'
+import { http } from '@/plugins/http'
+
+const props = defineProps(['modelValue', 'accounts'])
+const emit = defineEmits(['update:modelValue', 'createTask'])
+const creatingTask = ref(false)
+const form = ref(null)
+const items = ref([])
+const delay = ref({
+    min: 5,
+    max: 10
+})
+const rules = {
+    type: [{ required: true, message: '请选择任务类型', trigger: 'blur' }],
+    amountType: [{ required: true, message: '请选择金额类型', trigger: 'blur' }],
+    amount: [
+        {
+            validator: (rule, value, callback) => {
+                if (value.min === null || value.max === null) {
+                    return callback(new Error('请输入最小金额和最大金额'))
+                }
+                if (value.min > value.max) {
+                    return callback(new Error('最小金额不能大于最大金额'))
+                }
+                callback()
+            },
+            trigger: 'blur'
+        }
+    ],
+    percent: [
+        {
+            validator: (rule, value, callback) => {
+                if (value.min === null || value.max === null) {
+                    return callback(new Error('请输入最小百分比和最大百分比'))
+                }
+                if (value.min > value.max) {
+                    return callback(new Error('最小百分比不能大于最大百分比'))
+                }
+                callback()
+            },
+            trigger: 'blur'
+        }
+    ]
+}
+function onClose() {
+    emit('update:modelValue', false)
+}
+function addItem() {
+    items.value.push({
+        id: new Date().getTime(),
+        type: null,
+        amountType: 'amount',
+        amount: {
+            min: null,
+            max: null
+        },
+        percent: {
+            min: null,
+            max: null
+        }
+    })
+}
+
+function removeItem(index) {
+    items.value.splice(index, 1)
+}
+
+async function createTask() {
+    if (!items.value.length) {
+        return ElMessage.error('请添加任务')
+    }
+    console.log(form.value)
+    let valid = true
+    for (let f of form.value) {
+        try {
+            await f.validate()
+        } catch (error) {
+            valid = false
+        }
+    }
+    if (!valid) {
+        return
+    }
+    creatingTask.value = true
+    try {
+        await http.put('/tasks')
+        creatingTask.value = false
+        emit('update:modelValue', false)
+        ElMessage.success('创建成功')
+    } catch (error) {
+        creatingTask.value = false
+        ElMessage.error(error.message)
+    }
+}
+</script>
+<style lang="less">
+.create-task {
+    .el-dialog__header {
+        // padding: 0;
+    }
+    .el-dialog__body {
+        padding: 0 20px;
+    }
+    .el-form--inline .el-form-item {
+        margin-right: 10px;
+        margin-bottom: 0;
+    }
+}
+</style>

+ 8 - 115
src/views/HomeView.vue

@@ -10,48 +10,7 @@
             </ElCol>
         </ElRow>
     </ElConfigProvider>
-    <ElDialog v-model="showCreateTaskDialog" title="新建任务" width="500px">
-        <ElForm
-            :model="createTaskForm"
-            :rules="createTaskRule"
-            ref="createTaskFormRef"
-            label-position="right"
-            label-width="100px"
-        >
-            <ElFormItem prop="type" label="任务类型">
-                <ElSelect v-model="createTaskForm.type">
-                    <ElOption v-for="key in TaskType" :key="key" :label="TaskType[key]" :value="key"></ElOption>
-                </ElSelect>
-            </ElFormItem>
-            <ElFormItem
-                prop="amount"
-                label="金额"
-                v-if="!(createTaskForm.type === 'mint' || createTaskForm.type === 'removeLiquidity')"
-            >
-                <ElInputNumber v-model="createTaskForm.minAmount" class="mr-3 !w-24" :controls="false" />
-                ~
-                <ElInputNumber v-model="createTaskForm.maxAmount" class="ml-3 mr-4 !w-24" :controls="false" />
-            </ElFormItem>
-            <ElFormItem prop="startTime" label="执行时间">
-                <ElDatePicker type="datetime" v-model="createTaskForm.startTime"></ElDatePicker>
-            </ElFormItem>
-            <ElFormItem prop="interval" label="间隔时间">
-                <ElInputNumber v-model="createTaskForm.minInterval" :min="1" class="mr-3 !w-24" :controls="false" />
-                ~
-                <ElInputNumber
-                    v-model="createTaskForm.maxInterval"
-                    :min="1"
-                    class="ml-3 mr-3 !w-24"
-                    :controls="false"
-                />
-                秒
-            </ElFormItem>
-        </ElForm>
-        <template #footer>
-            <ElButton @click="showCreateTaskDialog = false">取消</ElButton>
-            <ElButton type="primary" @click="createTask" :loading="creatingTask">确定</ElButton>
-        </template>
-    </ElDialog>
+    <CreateTask v-model="showCreateTask" :accounts="selectedAccounts" />
 </template>
 
 <script setup>
@@ -62,85 +21,19 @@ import { TaskType } from '@/enums'
 import AccountsView from './AccountsView.vue'
 import TaskView from '@/views/TaskView.vue'
 import LogsView from './LogsView.vue'
+import CreateTask from './CreateTask.vue'
 
 const accountsView = ref(null)
 function selected() {
     return accountsView.value && accountsView.value.selected()
 }
-
-const showCreateTaskDialog = ref(false)
-const createTaskFormRef = ref(null)
-const createTaskForm = ref({})
-const createTaskRule = {
-    type: [{ required: true, message: '请选择类型' }],
-    amount: [
-        {
-            validator: (rule, value, callback) => {
-                if (createTaskForm.value.type !== 'min') {
-                    if (!(createTaskForm.value.minAmount && createTaskForm.value.maxAmount)) {
-                        callback(new Error('请输入金额'))
-                    } else if (Number(createTaskForm.value.minAmount) > Number(createTaskForm.value.maxAmount)) {
-                        callback(new Error('最小金额不能大于最大金额'))
-                    } else {
-                        callback()
-                    }
-                } else {
-                    callback()
-                }
-            }
-        }
-    ],
-    startTime: [{ required: true, message: '请选择执行时间' }],
-    interval: [
-        {
-            validator: (rule, value, callback) => {
-                if (!(createTaskForm.value.minInterval && createTaskForm.value.maxInterval)) {
-                    callback(new Error('请输入间隔时间'))
-                } else if (Number(createTaskForm.value.minInterval) > Number(createTaskForm.value.maxInterval)) {
-                    callback(new Error('最小间隔时间不能大于最大间隔时间'))
-                } else {
-                    callback()
-                }
-            }
-        }
-    ]
-}
-const creatingTask = ref(false)
+const showCreateTask = ref(false)
+const selectedAccounts = ref([])
 function onCreateTask() {
-    if (selected().length === 0) {
-        ElMessage.warning('请先选择账号')
-        return
+    selectedAccounts.value = selected()
+    if (selectedAccounts.value.length === 0) {
+        return ElMessage.warning('请选择账号')
     }
-    createTaskForm.value = {}
-    if (createTaskFormRef.value) {
-        createTaskFormRef.value.clearValidate()
-    }
-    showCreateTaskDialog.value = true
-}
-function createTask() {
-    createTaskFormRef.value.validate(async (valid) => {
-        if (valid) {
-            creatingTask.value = true
-            try {
-                await http.put('/tasks', {
-                    accounts: selected().map((i) => i.id),
-                    params: {
-                        minAmount: createTaskForm.value.minAmount,
-                        maxAmount: createTaskForm.value.maxAmount,
-                        minInterval: createTaskForm.value.minInterval,
-                        maxInterval: createTaskForm.value.maxInterval
-                    },
-                    type: createTaskForm.value.type,
-                    startTime: createTaskForm.value.startTime
-                })
-                ElMessage.success('任务添加成功')
-                creatingTask.value = false
-                showCreateTaskDialog.value = false
-            } catch (error) {
-                creatingTask.value = false
-                ElMessage.error(error.message)
-            }
-        }
-    })
+    showCreateTask.value = true
 }
 </script>

+ 5 - 0
yarn.lock

@@ -2719,6 +2719,11 @@ vue-demi@*, vue-demi@>=0.14.0:
   resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.0.tgz#dcfd9a9cf9bb62ada1582ec9042372cf67ca6190"
   integrity sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==
 
+vue-draggable-plus@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.npmmirror.com/vue-draggable-plus/-/vue-draggable-plus-0.2.1.tgz#d68a8c9c178ffea2ddf54f843332bb78da8937e5"
+  integrity sha512-BQmF1dudG6sIGxnZR7Bgi+lGOIFAQxld38HlhhzqlaWQHI6PVS5WgRPL4jD2Fy+pKMgnNhKuhz2f3lpczv2YDw==
+
 vue-eslint-parser@^9.0.1:
   version "9.1.1"
   resolved "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.1.1.tgz#3f4859be7e9bb7edaa1dc7edb05abffee72bf3dd"