|
@@ -1,259 +1,43 @@
|
|
|
<template>
|
|
|
<!-- <Spin class="loading-style" :spinning="loading" tip="Loading...">
|
|
|
<div v-if="!loading"> -->
|
|
|
- <Drawer
|
|
|
- :open="visible"
|
|
|
- title="群发消息"
|
|
|
- width="900"
|
|
|
- class="user-phase-drawer"
|
|
|
- @close="handleClose"
|
|
|
- >
|
|
|
+ <Drawer :open="visible" title="群发消息" width="800" class="user-phase-drawer" @close="handleClose">
|
|
|
<Steps :current="currentStep" size="default" class="step-style">
|
|
|
- <Step class="custom-step" title="设置消息条件"></Step>
|
|
|
- <Step class="custom-step" title="配置消息内容"></Step>
|
|
|
+ <Step class="custom-step" title="编辑群发"></Step>
|
|
|
+ <Step class="custom-step" title="编辑内容"></Step>
|
|
|
</Steps>
|
|
|
<!-- <div v-if="isDataLoaded"> -->
|
|
|
<div v-if="currentStep === 0" class="step-content">
|
|
|
- <Form
|
|
|
- :model="form"
|
|
|
- :label-col="{ span: 3 }"
|
|
|
- :wrapper-col="{ span: 19 }"
|
|
|
- ref="formRef"
|
|
|
- :rules="rules"
|
|
|
- >
|
|
|
- <FormItem
|
|
|
- label="任务名称"
|
|
|
- name="phaseName"
|
|
|
- :rules="[{ required: true, message: '请输入任务名称' }]"
|
|
|
- >
|
|
|
- <Input
|
|
|
- :disabled="btnDisabled"
|
|
|
- v-model:value="form.phaseName"
|
|
|
- placeholder="请输入任务名称"
|
|
|
- :maxlength="20"
|
|
|
- show-count
|
|
|
- />
|
|
|
+ <Form :model="form" :label-col="{ span: 3 }" :wrapper-col="{ span: 19 }" ref="formRef" :rules="rules">
|
|
|
+ <FormItem label="任务名称" name="taskName" :rules="[{ required: true, message: '请输入' }]">
|
|
|
+ <Input v-model:value="form.taskName" placeholder="请输入" :maxlength="20" show-count />
|
|
|
</FormItem>
|
|
|
- <FormItem label="筛选联系人"></FormItem>
|
|
|
- <!-- <div class="description">
|
|
|
- <InfoCircleOutlined />
|
|
|
- 主要用于执行任务的触发的条件,满足条件才可进入群发,转人工的动作
|
|
|
- </div> -->
|
|
|
- <!-- <FormItem
|
|
|
- label="选择条件"
|
|
|
- name="conditionType"
|
|
|
- :rules="[{ required: true, message: '请选择条件' }]"
|
|
|
- >
|
|
|
- <Radio.Group v-model:value="form.conditionType" :disabled="btnDisabled">
|
|
|
- <Radio value="1">客户标签</Radio>
|
|
|
- </Radio.Group>
|
|
|
- </FormItem> -->
|
|
|
- <FormItem
|
|
|
- label="条件关系"
|
|
|
- name="conditionOperator"
|
|
|
- :rules="[{ required: true, message: '请选择条件关系' }]"
|
|
|
- >
|
|
|
- <Radio.Group v-model:value="form.conditionOperator" :disabled="btnDisabled">
|
|
|
- <Radio value="1">满足所有条件</Radio>
|
|
|
- <Radio value="2">满足一个条件即可</Radio>
|
|
|
- </Radio.Group>
|
|
|
+ <FormItem label="发送账号" name="fromwxid" :rules="[{ required: true, message: '请选择' }]">
|
|
|
+ <Select v-model:value="form.fromwxid" placeholder="请选择" :options="accountList"></Select>
|
|
|
</FormItem>
|
|
|
- <FormItem
|
|
|
- label="触发条件"
|
|
|
- name="conditionList"
|
|
|
- :rules="[{ required: true, message: '请选择触发条件' }]"
|
|
|
- >
|
|
|
- <Button
|
|
|
- :disabled="btnDisabled"
|
|
|
- @click="addContent"
|
|
|
- style="
|
|
|
- box-shadow: none;
|
|
|
- color: #307ef2;
|
|
|
- display: inline-block;
|
|
|
- border: none;
|
|
|
- background: none;
|
|
|
- "
|
|
|
- >
|
|
|
- <PlusCircleOutlined style="color: #307ef2; display: inline-block" />
|
|
|
- 添加
|
|
|
- </Button>
|
|
|
- <div v-if="form.conditionList.length > 0" class="concrete-content-container">
|
|
|
- <div
|
|
|
- v-for="(item, index) in form.conditionList"
|
|
|
- :key="index"
|
|
|
- class="concrete-content-item"
|
|
|
- >
|
|
|
- <span>标签</span>
|
|
|
- <FormItem :name="'equal-' + index">
|
|
|
- <Select
|
|
|
- :disabled="btnDisabled"
|
|
|
- v-model:value="item.equal"
|
|
|
- :options="equalList"
|
|
|
- :style="{ width: '80px', margin: '0 5px' }"
|
|
|
- ></Select>
|
|
|
- </FormItem>
|
|
|
- <FormItem :name="'labelIdList-' + index" :style="{ display: 'contents' }">
|
|
|
- <Select
|
|
|
- :disabled="btnDisabled"
|
|
|
- v-model:value="item.labelIdList"
|
|
|
- :options="actionLabel"
|
|
|
- allowClear
|
|
|
- mode="multiple"
|
|
|
- size="middle"
|
|
|
- placeholder="请选择"
|
|
|
- :style="{ width: '240px', margin: '0 5px' }"
|
|
|
- :max-tag-count="1"
|
|
|
- ></Select>
|
|
|
- </FormItem>
|
|
|
- <Button
|
|
|
- style="
|
|
|
- color: #307ef2;
|
|
|
- box-shadow: none;
|
|
|
- display: inline-block;
|
|
|
- border: none;
|
|
|
- background: none;
|
|
|
- "
|
|
|
- :disabled="btnDisabled"
|
|
|
- v-if="form.conditionList.length > 1"
|
|
|
- @click="removeContent(index)"
|
|
|
- >
|
|
|
- <CloseCircleOutlined style="color: #d3d2d3" />
|
|
|
- </Button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <FormItem label="标签" name="labels">
|
|
|
+ <Select v-model:value="form.labels" :options="actionLabel" allowClear mode="multiple" size="middle"
|
|
|
+ placeholder="请选择" :style="{ margin: '0 5px' }"></Select>
|
|
|
+ <span v-show="form.labels.length === 0" class="warning-style">请选择标签</span>
|
|
|
</FormItem>
|
|
|
- <FormItem label="选择发送时间"></FormItem>
|
|
|
- <FormItem
|
|
|
- label="发送方式"
|
|
|
- name="conditionOperator"
|
|
|
- :rules="[{ required: true, message: '请选择发送方式' }]"
|
|
|
- >
|
|
|
- <Radio.Group v-model:value="form.conditionOperator" :disabled="btnDisabled">
|
|
|
+ <FormItem label="发送方式" name="conditionOperator" :rules="[{ required: true, message: '请选择发送方式' }]">
|
|
|
+ <Radio.Group v-model:value="form.conditionOperator">
|
|
|
<Radio value="1">立即发送</Radio>
|
|
|
<Radio value="2">定时发送</Radio>
|
|
|
</Radio.Group>
|
|
|
</FormItem>
|
|
|
- <FormItem
|
|
|
- label="发送时间"
|
|
|
- name="conditionOperator"
|
|
|
- :rules="[{ required: true, message: '请选择发送时间' }]"
|
|
|
- >
|
|
|
- <DatePicker
|
|
|
- v-model:value="form.dateRange"
|
|
|
- placeholder="请选择发送时间"
|
|
|
- format="YYYY-MM-DD HH:mm:ss"
|
|
|
- :disabled-date="disabledDate"
|
|
|
- :show-time="{ defaultValue: dayjs('00:00:00', 'HH:mm:ss') }"
|
|
|
- />
|
|
|
+ <FormItem label="发送时间" name="sendTimeStr" :rules="[{ required: true, message: '请选择发送时间' }]">
|
|
|
+ <DatePicker v-model:value="form.sendTimeStr" placeholder="请选择发送时间" format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ :disabled-date="disabledDate" :show-time="{ defaultValue: dayjs('00:00:00', 'HH:mm:ss') }" />
|
|
|
</FormItem>
|
|
|
</Form>
|
|
|
</div>
|
|
|
+ <!-- 第二步 -->
|
|
|
<div v-if="currentStep === 1" class="step-content">
|
|
|
- <Form
|
|
|
- :model="taskForm"
|
|
|
- :label-col="{ span: 3 }"
|
|
|
- :wrapper-col="{ span: 19 }"
|
|
|
- ref="taskFormRef"
|
|
|
- >
|
|
|
- <FormItem label="执行任务" name="taskType">
|
|
|
- <Button
|
|
|
- :disabled="btnDisabled"
|
|
|
- :class="isMsgAction ? 'action-btn' : 'btn-style'"
|
|
|
- @click="setTaskType('sendMessage')"
|
|
|
- >
|
|
|
- <template #icon>
|
|
|
- <CommentOutlined />
|
|
|
- </template>
|
|
|
- 发消息
|
|
|
- </Button>
|
|
|
- <!-- <Button
|
|
|
- :disabled="btnDisabled"
|
|
|
- :class="isTagAction ? 'action-btn' : 'btn-style'"
|
|
|
- @click="setTaskType('tag')"
|
|
|
- >
|
|
|
- <template #icon>
|
|
|
- <TagsOutlined />
|
|
|
- </template>
|
|
|
- 打标签
|
|
|
- </Button> -->
|
|
|
+ <Form :model="taskForm" :label-col="{ span: 3 }" :wrapper-col="{ span: 19 }" ref="taskFormRef">
|
|
|
+ <FormItem label="" name="msg" :rules="[{ required: true, message: '请输入消息内容' }]">
|
|
|
+ <MsgContant v-model:value="taskForm.msg" />
|
|
|
</FormItem>
|
|
|
- <!-- 发消息 -->
|
|
|
- <Collapse
|
|
|
- v-show="isMsgAction"
|
|
|
- v-model:activeKey="activeKey"
|
|
|
- collapsible="header"
|
|
|
- class="custom-collapse"
|
|
|
- >
|
|
|
- <Collapse.Panel key="1" class="custom-collapse-panel">
|
|
|
- <template #header>
|
|
|
- <div @click.stop="toggleTimeoutAction" style="display: flex; align-items: center">
|
|
|
- <MessageOutlined style="color: #83b14e" />
|
|
|
-
|
|
|
- <span>发消息</span>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <div @click.stop>
|
|
|
- <FormItem label="发送方式" name="sendType">
|
|
|
- <Radio.Group v-model:value="taskForm.sendType" :disabled="btnDisabled">
|
|
|
- <Radio value="immediate">立即发送</Radio>
|
|
|
- <!-- <Radio value="scheduled">定时发送</Radio> -->
|
|
|
- </Radio.Group>
|
|
|
- </FormItem>
|
|
|
- <!-- 根据发送方式显示 MsgContant 或在折叠面板中展示 -->
|
|
|
- <div v-if="taskForm.sendType === 'immediate'">
|
|
|
- <FormItem
|
|
|
- label=""
|
|
|
- name="actionMessage"
|
|
|
- :rules="[{ required: true, message: '请输入消息内容' }]"
|
|
|
- >
|
|
|
- <MsgContant v-model:value="taskForm.actionMessage" :msgDisabled="btnDisabled" />
|
|
|
- </FormItem>
|
|
|
- <!-- <component :is="MsgContant" /> -->
|
|
|
- </div>
|
|
|
- <TimedSending v-else />
|
|
|
- </div>
|
|
|
- </Collapse.Panel>
|
|
|
- </Collapse>
|
|
|
- <!-- 打标签 -->
|
|
|
- <!-- <Collapse
|
|
|
- v-show="isTagAction"
|
|
|
- v-model:activeKey="activeKeyTag"
|
|
|
- collapsible="header"
|
|
|
- class="custom-collapse-tag"
|
|
|
- >
|
|
|
- <Collapse.Panel key="1" class="tag-collapse-panel">
|
|
|
- <template #header>
|
|
|
- <div @click.stop="toggleTimeoutAction" style="display: flex; align-items: center">
|
|
|
- <TagOutlined style="color: #6f9ce5" />
|
|
|
-
|
|
|
- <span>打标签</span>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <div @click.stop>
|
|
|
- <FormItem
|
|
|
- label="用户进入当前阶段时,可以打上标签"
|
|
|
- name="tagging"
|
|
|
- v-if="msgAction"
|
|
|
- :labelCol="{ span: 8 }"
|
|
|
- >
|
|
|
- <Select
|
|
|
- :disabled="btnDisabled"
|
|
|
- v-model:value="taskForm.tagValue"
|
|
|
- :options="actionLabel"
|
|
|
- allowClear
|
|
|
- mode="multiple"
|
|
|
- size="middle"
|
|
|
- placeholder="请选择"
|
|
|
- :style="{ width: '240px', margin: '0 5px' }"
|
|
|
- :max-tag-count="1"
|
|
|
- ></Select>
|
|
|
- <span v-show="taskForm.tagValue.length === 0" class="warning-style">
|
|
|
- 请选择标签
|
|
|
- </span>
|
|
|
- </FormItem>
|
|
|
- </div>
|
|
|
- </Collapse.Panel>
|
|
|
- </Collapse> -->
|
|
|
</Form>
|
|
|
</div>
|
|
|
<div class="steps-action">
|
|
@@ -269,481 +53,301 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { unref, defineProps, defineEmits, ref, toRefs, watch, reactive, onMounted } from 'vue';
|
|
|
- import {
|
|
|
- Drawer,
|
|
|
- Form,
|
|
|
- FormItem,
|
|
|
- Input,
|
|
|
- Radio,
|
|
|
- Button,
|
|
|
- Steps,
|
|
|
- Step,
|
|
|
- Collapse,
|
|
|
- Select,
|
|
|
- Spin,
|
|
|
- message,
|
|
|
- DatePicker,
|
|
|
- } from 'ant-design-vue';
|
|
|
- import {
|
|
|
- InfoCircleOutlined,
|
|
|
- CommentOutlined,
|
|
|
- TagsOutlined,
|
|
|
- PlusCircleOutlined,
|
|
|
- CloseCircleOutlined,
|
|
|
- MessageOutlined,
|
|
|
- TagOutlined,
|
|
|
- } from '@ant-design/icons-vue';
|
|
|
- import type { FormInstance } from 'ant-design-vue';
|
|
|
- import { getLabelSelectList } from '@/api/wechat/label';
|
|
|
- // import HtmlTextarea from './htmlTextarea.vue';
|
|
|
- import dayjs, { Dayjs } from 'dayjs';
|
|
|
- import MsgContant from './msgContant.vue';
|
|
|
- import TimedSending from './timedSending.vue';
|
|
|
-
|
|
|
- import {
|
|
|
- addSopTaskStage,
|
|
|
- getSopStageDetailById,
|
|
|
- getSopStageList,
|
|
|
- editSopTaskStage,
|
|
|
- } from '@/api/wechat/sopTask';
|
|
|
- // import { useStore } from '../stores/index';
|
|
|
- // let store = useStore();
|
|
|
- // let {
|
|
|
- // sopLabelList,
|
|
|
- // sopStageId,
|
|
|
- // sopTaskId,
|
|
|
- // sopTaskDtat,
|
|
|
- // setSopStageId,
|
|
|
- // setSopStageList,
|
|
|
- // setStageDrawer,
|
|
|
- // } = store;
|
|
|
-
|
|
|
- // name: 'UserPhasesDrawer',
|
|
|
- const props = defineProps<{
|
|
|
- visible: boolean;
|
|
|
- // stageId: {
|
|
|
- // type: Number; // 支持 number 和 ref 类型
|
|
|
- // required: true;
|
|
|
- // };
|
|
|
- btnDisabled: {
|
|
|
- type: Boolean;
|
|
|
- default: false;
|
|
|
- };
|
|
|
- }>();
|
|
|
- const emit = defineEmits<{
|
|
|
- (event: 'update:open', value: boolean): void;
|
|
|
- (event: 'update:getStageList', value: { value: boolean; id: number }): void;
|
|
|
- }>();
|
|
|
- const { visible, btnDisabled } = toRefs(props);
|
|
|
- const loading = ref(false);
|
|
|
- const currentStep = ref(0);
|
|
|
- const formRef = ref<FormInstance | null>(null);
|
|
|
- const taskFormRef = ref<FormInstance | null>(null);
|
|
|
- const dayValue = ref<number>(1);
|
|
|
- const strValue = ref<string>('09:00:00');
|
|
|
- // const tagValue = ref<number>();
|
|
|
- const labelIsShow = ref<boolean>(false);
|
|
|
- // 定义动态组件插槽或具名插槽
|
|
|
- // const MsgContantSlot = MsgContant;
|
|
|
- // 定义选项数组
|
|
|
- // const actionLabel = sopLabelList;
|
|
|
- const actionLabel = ref([]);
|
|
|
- const equalList = [
|
|
|
- { label: '是', value: 1 },
|
|
|
- { label: '不是', value: 2 },
|
|
|
- ];
|
|
|
- const form = reactive({
|
|
|
- phaseName: '',
|
|
|
- conditionType: '1', //1:客户标签2:基本信息
|
|
|
- conditionOperator: '1',
|
|
|
- conditionList: [],
|
|
|
- dateRange: '',
|
|
|
- });
|
|
|
- const rules = {
|
|
|
- phaseName: [{ required: true, message: '请输入阶段名称', trigger: 'blur' }],
|
|
|
- conditionOperator: [{ required: true, message: '请选择条件关系', trigger: 'change' }],
|
|
|
- conditionList: [{ required: true, message: '请选择', trigger: 'change' }],
|
|
|
- // 'conditionList[0].labelIdList': [{ required: true, message: '请输入', trigger: 'blur' }],
|
|
|
- };
|
|
|
- const initialForm = reactive({
|
|
|
- phaseName: '',
|
|
|
- conditionType: '1',
|
|
|
- conditionOperator: '1',
|
|
|
- conditionList: [],
|
|
|
- });
|
|
|
- const taskForm = reactive({
|
|
|
- taskType: 'sendMessage',
|
|
|
- sendType: 'immediate',
|
|
|
- actionMessage: [{ type: 1, content: '' }],
|
|
|
- tagValue: [],
|
|
|
- });
|
|
|
- const initialTaskForm = reactive({
|
|
|
- taskType: 'sendMessage',
|
|
|
- sendType: 'immediate',
|
|
|
- actionMessage: [{ type: 1, content: '' }],
|
|
|
- tagValue: [],
|
|
|
- });
|
|
|
- const activeKey = ref<number | string>('1');
|
|
|
- const activeKeyTiem = ref<number | string>('time1');
|
|
|
- const activeKeyTag = ref<number | string>('1');
|
|
|
- // const msgAction = ref<boolean>(false);
|
|
|
- const msgAction = ref(taskForm.taskType === 'sendMessage');
|
|
|
- const isMsgAction = ref<boolean>(true);
|
|
|
- const isTagAction = ref<boolean>(false);
|
|
|
- // const isDataLoaded = ref(false); // 控制表单的渲染
|
|
|
- onMounted(async () => {
|
|
|
- let res = await getLabelSelectList({ page: 1, pageSize: 1000, type: 1 });
|
|
|
- actionLabel.value = res.data;
|
|
|
- // if (unref(stageId)) {
|
|
|
- // getStageDetail(unref(stageId));
|
|
|
- // } else {
|
|
|
- // console.log('新建----');
|
|
|
- // resetForms();
|
|
|
- // }
|
|
|
- });
|
|
|
+import { unref, defineProps, defineEmits, ref, toRefs, watch, reactive, onMounted } from 'vue';
|
|
|
+import {
|
|
|
+ Drawer,
|
|
|
+ Form,
|
|
|
+ FormItem,
|
|
|
+ Input,
|
|
|
+ Radio,
|
|
|
+ Button,
|
|
|
+ Steps,
|
|
|
+ Step,
|
|
|
+ Select,
|
|
|
+ Spin,
|
|
|
+ DatePicker,
|
|
|
+} from 'ant-design-vue';
|
|
|
+import type { FormInstance } from 'ant-design-vue';
|
|
|
+import { getLabelSelectList } from '@/api/wechat/label';
|
|
|
+// import HtmlTextarea from './htmlTextarea.vue';
|
|
|
+import dayjs, { Dayjs } from 'dayjs';
|
|
|
+import MsgContant from './msgContant.vue';
|
|
|
|
|
|
- const disabledDate = (current: Dayjs) => {
|
|
|
- return current && current < dayjs().endOf('day');
|
|
|
- };
|
|
|
+import { getSopStageDetailById, editSopTaskStage } from '@/api/wechat/sopTask';
|
|
|
+import { createBatchMsg, } from '@/api/wechat/batchMsg';
|
|
|
|
|
|
- function nextStep() {
|
|
|
- if (currentStep.value === 0) {
|
|
|
- formRef.value
|
|
|
- ?.validate()
|
|
|
- .then((res) => {
|
|
|
- const allValid = res.conditionList.every((item) => item.labelIdList.length > 0);
|
|
|
- if (!allValid) {
|
|
|
- message.warning('请选择完整的标签!');
|
|
|
- return;
|
|
|
- } else {
|
|
|
- currentStep.value += 1;
|
|
|
- }
|
|
|
- })
|
|
|
- .catch((error) => {
|
|
|
- console.error('校验失败:', error);
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function prevStep() {
|
|
|
- if (currentStep.value > 0) {
|
|
|
- currentStep.value -= 1;
|
|
|
- }
|
|
|
- }
|
|
|
+const props = defineProps<{
|
|
|
+ visible: boolean;
|
|
|
+ // stageId: {
|
|
|
+ // type: Number; // 支持 number 和 ref 类型
|
|
|
+ // required: true;
|
|
|
+ // };
|
|
|
+ // btnDisabled: {
|
|
|
+ // type: Boolean;
|
|
|
+ // default: false;
|
|
|
+ // };
|
|
|
+}>();
|
|
|
+const emit = defineEmits<{
|
|
|
+ (event: 'update:open', value: boolean): void;
|
|
|
+ (event: 'update:getStageList', value: { value: boolean; id: number }): void;
|
|
|
+}>();
|
|
|
+const { visible, } = toRefs(props);
|
|
|
+const loading = ref(false);
|
|
|
+const currentStep = ref(0);
|
|
|
+const formRef = ref<FormInstance | null>(null);
|
|
|
+const taskFormRef = ref<FormInstance | null>(null);
|
|
|
|
|
|
- function addContent() {
|
|
|
- labelIsShow.value = true;
|
|
|
- form.conditionList.push({ equal: 1, labelIdList: [] });
|
|
|
- }
|
|
|
+const actionLabel = ref([]);
|
|
|
+const accountList = ref([]);
|
|
|
|
|
|
- function removeContent(index: number) {
|
|
|
- form.conditionList.splice(index, 1);
|
|
|
- }
|
|
|
+const form = reactive({
|
|
|
+ taskName: '',
|
|
|
+ fromwxid: '',
|
|
|
+ conditionOperator: '1',
|
|
|
+ // conditionList: [],
|
|
|
+ sendTimeStr: '',
|
|
|
+ labels: [],
|
|
|
+});
|
|
|
+const rules = {
|
|
|
+ taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
|
|
|
+ conditionOperator: [{ required: true, message: '请选择条件关系', trigger: 'change' }],
|
|
|
+ // conditionList: [{ required: true, message: '请选择', trigger: 'change' }],
|
|
|
+ // 'conditionList[0].labelIdList': [{ required: true, message: '请输入', trigger: 'blur' }],
|
|
|
+};
|
|
|
+const initialForm = reactive({
|
|
|
+ taskName: '',
|
|
|
+ conditionOperator: '1',
|
|
|
+ conditionList: [],
|
|
|
+ fromwxid: '',
|
|
|
+ sendTimeStr: '',
|
|
|
+ labels: [],
|
|
|
+});
|
|
|
+const taskForm = reactive({
|
|
|
+ // taskType: 'sendMessage',
|
|
|
+ // sendType: 'immediate',
|
|
|
+ msg: [{ type: 1, content: '' }],
|
|
|
|
|
|
- function resetForms() {
|
|
|
- Object.assign(form, initialForm);
|
|
|
- Object.assign(taskForm, initialTaskForm);
|
|
|
- currentStep.value = 0;
|
|
|
- }
|
|
|
+});
|
|
|
+const initialTaskForm = reactive({
|
|
|
+ // taskType: 'sendMessage',
|
|
|
+ // sendType: 'immediate',
|
|
|
+ msg: [{ type: 1, content: '' }],
|
|
|
+});
|
|
|
+const activeKey = ref<number | string>('1');
|
|
|
+const activeKeyTiem = ref<number | string>('time1');
|
|
|
+const activeKeyTag = ref<number | string>('1');
|
|
|
+// const msgAction = ref<boolean>(false);
|
|
|
+// const msgAction = ref(taskForm.taskType === 'sendMessage');
|
|
|
+const isMsgAction = ref<boolean>(true);
|
|
|
+const isTagAction = ref<boolean>(false);
|
|
|
+// const isDataLoaded = ref(false); // 控制表单的渲染
|
|
|
+onMounted(async () => {
|
|
|
+ let res = await getLabelSelectList({ page: 1, pageSize: 1000, type: 1 });
|
|
|
+ actionLabel.value = res.data;
|
|
|
+ accountList.value = res.data;
|
|
|
+ // if (unref(stageId)) {
|
|
|
+ // getStageDetail(unref(stageId));
|
|
|
+ // } else {
|
|
|
+ // console.log('新建----');
|
|
|
+ // resetForms();
|
|
|
+ // }
|
|
|
+});
|
|
|
|
|
|
- async function getStageDetail(id) {
|
|
|
- // 模拟 API 调用
|
|
|
- let data = await getSopStageDetailById({ id });
|
|
|
- // 填充 form 数据
|
|
|
- Object.assign(form, {
|
|
|
- phaseName: data.data.name,
|
|
|
- // conditionType: String(data.data.conditionType),
|
|
|
- conditionOperator: String(data.data.conditionOperator),
|
|
|
- conditionList: data.data.conditionList || [],
|
|
|
- });
|
|
|
- const taskTypes = [];
|
|
|
- if (data.data.actionMessage.length > 0) {
|
|
|
- taskTypes.push('sendMessage');
|
|
|
- }
|
|
|
- if (data.data.actionLabel.length > 0) {
|
|
|
- taskTypes.push('tag');
|
|
|
- }
|
|
|
- // 填充 taskForm 数据
|
|
|
- Object.assign(taskForm, {
|
|
|
- taskType: taskTypes,
|
|
|
- sendType: 'immediate',
|
|
|
- actionMessage: data.data.actionMessage || [{ type: 1, content: '' }],
|
|
|
- tagValue: data.data.actionLabel || [],
|
|
|
- });
|
|
|
- // 根据 taskType 设置 isMsgAction 和 isTagAction
|
|
|
- isMsgAction.value = taskTypes.includes('sendMessage');
|
|
|
- isTagAction.value = taskTypes.includes('tag');
|
|
|
- }
|
|
|
+const disabledDate = (current: Dayjs) => {
|
|
|
+ return current && current < dayjs().endOf('day');
|
|
|
+};
|
|
|
|
|
|
- function processArray(array: any[]) {
|
|
|
- array.forEach((item) => {
|
|
|
- if (item.type === 2 && Array.isArray(item.content)) {
|
|
|
- const contentString = item.content[0]; // 假设content只有一个元素
|
|
|
- const filename = contentString.split('/').pop(); // 获取最后一个/后的值
|
|
|
- item.content = contentString; // 将content数组转成字符串
|
|
|
- item.meta = { filename }; // 添加meta对象
|
|
|
- }
|
|
|
- });
|
|
|
- return array;
|
|
|
- }
|
|
|
- async function submitForm() {
|
|
|
- if (!btnDisabled.value) {
|
|
|
- // 提交表单逻辑 conditionType,
|
|
|
- const { phaseName, conditionOperator, conditionList } = form;
|
|
|
- const { taskType, sendType, actionMessage, tagValue } = taskForm;
|
|
|
- processArray(actionMessage);
|
|
|
- const requestData = {
|
|
|
- name: phaseName,
|
|
|
- // conditionType: ~~conditionType,
|
|
|
- conditionType: 1,
|
|
|
- conditionOperator: ~~conditionOperator,
|
|
|
- conditionList,
|
|
|
- taskType,
|
|
|
- sendType,
|
|
|
- actionMessage,
|
|
|
- actionLabel: tagValue,
|
|
|
- };
|
|
|
- const allData = actionMessage.every((item) => item.content.trim() !== '');
|
|
|
- if ((isMsgAction.value && !allData) || (isTagAction.value && tagValue.length === 0)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- if (unref(stageId)) {
|
|
|
- // 编辑
|
|
|
- loading.value = true;
|
|
|
- console.log('编辑阶段');
|
|
|
- const id = unref(stageId);
|
|
|
- let response = await editSopTaskStage({ id, ...requestData });
|
|
|
- if (response && response.code == 0) {
|
|
|
- loading.value = false;
|
|
|
- emit('update:getStageList', { value: true, id });
|
|
|
- console.log('编辑成功');
|
|
|
- handleClose();
|
|
|
- } else {
|
|
|
- console.error(response.code, '编辑失败');
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 新增
|
|
|
- // console.log('新增阶段', sopTaskId, store.sopTaskId);
|
|
|
- loading.value = true;
|
|
|
- let response = await addSopTaskStage({ taskId: 1, ...requestData });
|
|
|
- if (response && response.code === 0) {
|
|
|
- console.log('新增成功');
|
|
|
- loading.value = false;
|
|
|
- // getStageList()
|
|
|
- emit('update:getStageList', { value: true, id: response.data });
|
|
|
- // setSopStageId(response.data); // 更新 sopStageId
|
|
|
- handleClose();
|
|
|
- } else {
|
|
|
- loading.value = false;
|
|
|
- console.error('新增失败');
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- handleClose();
|
|
|
- }
|
|
|
- }
|
|
|
+function nextStep() {
|
|
|
+ if (currentStep.value === 0) {
|
|
|
+ formRef.value
|
|
|
+ ?.validate()
|
|
|
+ .then((res) => {
|
|
|
+ // const allValid = res.conditionList.every((item) => item.labelIdList.length > 0);
|
|
|
+ // if (!allValid) {
|
|
|
+ // message.warning('请选择完整的标签!');
|
|
|
+ // return;
|
|
|
+ // } else {
|
|
|
+ currentStep.value += 1;
|
|
|
+ // }
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.error('校验失败:', error);
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- // 打开或关闭抽屉
|
|
|
- function handleClose() {
|
|
|
- if (visible.value) {
|
|
|
- resetForms();
|
|
|
- }
|
|
|
- emit('update:open', false);
|
|
|
+function prevStep() {
|
|
|
+ if (currentStep.value > 0) {
|
|
|
+ currentStep.value -= 1;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- // function resetForms () {
|
|
|
- // Object.assign(form, initialForm);
|
|
|
- // Object.assign(taskForm, initialTaskForm);
|
|
|
- // msgAction.value = '';
|
|
|
- // isMsgAction.value = true;
|
|
|
- // isTagAction.value = false;
|
|
|
- // dayValue.value = 1;
|
|
|
- // strValue.value = '09:00:00';
|
|
|
- // // tagValue.value = [];
|
|
|
- // };
|
|
|
+function resetForms() {
|
|
|
+ Object.assign(form, initialForm);
|
|
|
+ Object.assign(taskForm, initialTaskForm);
|
|
|
+ currentStep.value = 0;
|
|
|
+}
|
|
|
|
|
|
- // 在打开抽屉时保存初始状态
|
|
|
- watch(visible, (newVal) => {
|
|
|
- if (newVal) {
|
|
|
- Object.assign(initialForm, { ...form });
|
|
|
- Object.assign(initialTaskForm, { ...taskForm });
|
|
|
- }
|
|
|
+async function getStageDetail(id) {
|
|
|
+ // 模拟 API 调用
|
|
|
+ let data = await getSopStageDetailById({ id });
|
|
|
+ // 填充 form 数据
|
|
|
+ Object.assign(form, {
|
|
|
+ taskName: data.data.name,
|
|
|
+ fromwxid: data.data.fromwxid,
|
|
|
+ conditionOperator: String(data.data.conditionOperator),
|
|
|
+ labels: data.data.msg || [],
|
|
|
+ // conditionList: data.data.conditionList || [],
|
|
|
+ });
|
|
|
+ // const taskTypes = [];
|
|
|
+ // if (data.data.msg.length > 0) {
|
|
|
+ // taskTypes.push('sendMessage');
|
|
|
+ // }
|
|
|
+ // if (data.data.actionLabel.length > 0) {
|
|
|
+ // taskTypes.push('tag');
|
|
|
+ // }
|
|
|
+ // 填充 taskForm 数据
|
|
|
+ Object.assign(taskForm, {
|
|
|
+ // taskType: taskTypes,
|
|
|
+ // sendType: 'immediate',
|
|
|
+ msg: data.data.msg || [{ type: 1, content: '' }],
|
|
|
+ // labels: data.data.actionLabel || [],
|
|
|
});
|
|
|
+ // 根据 taskType 设置 isMsgAction 和 isTagAction
|
|
|
+ // isMsgAction.value = taskTypes.includes('sendMessage');
|
|
|
+ // isTagAction.value = taskTypes.includes('tag');
|
|
|
+}
|
|
|
|
|
|
- // 设置任务类型
|
|
|
- function setTaskType(type: string) {
|
|
|
- taskForm.taskType = type;
|
|
|
- if (type === 'tag') {
|
|
|
- isTagAction.value = !isTagAction.value;
|
|
|
- msgAction.value = type === 'tag';
|
|
|
- if (!isTagAction.value) {
|
|
|
- taskForm.taskType = '';
|
|
|
- taskForm.tagValue = [];
|
|
|
- }
|
|
|
- } else if (type === 'sendMessage') {
|
|
|
- msgAction.value = type === 'sendMessage';
|
|
|
- isMsgAction.value = !isMsgAction.value;
|
|
|
- if (!isMsgAction.value) {
|
|
|
- taskForm.taskType = '';
|
|
|
- taskForm.actionMessage = [{ type: 1, content: '' }];
|
|
|
- }
|
|
|
+function processArray(array: any[]) {
|
|
|
+ array.forEach((item) => {
|
|
|
+ if (item.type === 2 && Array.isArray(item.content)) {
|
|
|
+ const contentString = item.content[0]; // 假设content只有一个元素
|
|
|
+ const filename = contentString.split('/').pop(); // 获取最后一个/后的值
|
|
|
+ item.content = contentString; // 将content数组转成字符串
|
|
|
+ item.meta = { filename }; // 添加meta对象
|
|
|
}
|
|
|
- // taskForm.taskType = type;
|
|
|
- // msgAction.value = type === 'sendMessage';
|
|
|
- // isMsgAction.value = type === 'sendMessage';
|
|
|
- // isTagAction.value = type === 'tag';
|
|
|
- }
|
|
|
- // const setTaskType = (taskType: string) => {
|
|
|
- // if(taskType === 'tag'){
|
|
|
- // isTagAction.value = !isTagAction.value;
|
|
|
- // }else if(taskType === 'sendMessage'){
|
|
|
- // isMsgAction.value = !isMsgAction.value;
|
|
|
+ });
|
|
|
+ return array;
|
|
|
+}
|
|
|
+async function submitForm() {
|
|
|
+ // if (!btnDisabled.value) {
|
|
|
+ // 提交表单逻辑 ,
|
|
|
+ const { taskName, fromwxid, conditionOperator, labels, sendTimeStr } = form;
|
|
|
+ const { msg } = taskForm;
|
|
|
+ processArray(msg);
|
|
|
+ const requestData = {
|
|
|
+ taskName,
|
|
|
+ fromwxid,
|
|
|
+ sendTimeStr,
|
|
|
+ conditionOperator: ~~conditionOperator,
|
|
|
+ msg,
|
|
|
+ labels,
|
|
|
+ };
|
|
|
+ const allData = msg.every((item) => item.content.trim() !== '');
|
|
|
+ if ((isMsgAction.value && !allData) || (isTagAction.value && labels.length === 0)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // if (unref(stageId)) {
|
|
|
+ // 编辑
|
|
|
+ // loading.value = true;
|
|
|
+ // console.log('编辑群发消息');
|
|
|
+ // const id = unref(stageId);
|
|
|
+ // let response = await editSopTaskStage({ id, ...requestData });
|
|
|
+ // if (response && response.code == 0) {
|
|
|
+ // loading.value = false;
|
|
|
+ // emit('update:getStageList', { value: true, id });
|
|
|
+ // console.log('编辑成功');
|
|
|
+ // handleClose();
|
|
|
+ // } else {
|
|
|
+ // console.error(response.code, '编辑失败');
|
|
|
+ // }
|
|
|
+ // } else {
|
|
|
+ // 新增
|
|
|
+ console.log('新增去发消息', ...requestData);
|
|
|
+ loading.value = true;
|
|
|
+ // let response = await createBatchMsg({ ...requestData });
|
|
|
+ // if (response && response.code === 0) {
|
|
|
+ // console.log('新增成功');
|
|
|
+ // loading.value = false;
|
|
|
+ // // emit('update:getStageList', { value: true, id: response.data });
|
|
|
+ // handleClose();
|
|
|
+ // } else {
|
|
|
+ // loading.value = false;
|
|
|
+ // console.error('新增失败');
|
|
|
+ // }
|
|
|
// }
|
|
|
- // if (taskForm.taskType === taskType) {
|
|
|
- // // Toggle the state if the taskType is already the same
|
|
|
- // msgAction.value = !msgAction.value;
|
|
|
- // activeKey.value = msgAction.value ? ['1'] : [];
|
|
|
// } else {
|
|
|
- // taskForm.taskType = taskType;
|
|
|
- // msgAction.value = taskType === 'sendMessage';
|
|
|
- // activeKey.value = msgAction.value ? ['1'] : [];
|
|
|
+ handleClose();
|
|
|
// }
|
|
|
- // };
|
|
|
+}
|
|
|
|
|
|
- function toggleTimeoutAction() {
|
|
|
- // 切换折叠面板的动作
|
|
|
- if (taskForm.taskType === 'scheduled') {
|
|
|
- msgAction.value = !msgAction.value;
|
|
|
- if (msgAction.value) {
|
|
|
- activeKeyTiem.value = ['time1'];
|
|
|
- } else {
|
|
|
- activeKeyTiem.value = [];
|
|
|
- }
|
|
|
- }
|
|
|
+// 打开或关闭抽屉
|
|
|
+function handleClose() {
|
|
|
+ if (visible.value) {
|
|
|
+ resetForms();
|
|
|
}
|
|
|
- // 切换超时动作
|
|
|
- // const toggleTimeoutAction = () => {
|
|
|
- // activeKeyTiem.value = activeKeyTiem.value ? '' : 'time1';
|
|
|
- // };
|
|
|
+ emit('update:open', false);
|
|
|
+}
|
|
|
+
|
|
|
+// 在打开抽屉时保存初始状态
|
|
|
+watch(visible, (newVal) => {
|
|
|
+ if (newVal) {
|
|
|
+ Object.assign(initialForm, { ...form });
|
|
|
+ Object.assign(initialTaskForm, { ...taskForm });
|
|
|
+ }
|
|
|
+});
|
|
|
</script>
|
|
|
<style scoped lang="less">
|
|
|
- .user-phase-drawer {
|
|
|
- width: 900px;
|
|
|
- height: 100vh;
|
|
|
- }
|
|
|
- .concrete-content-container {
|
|
|
- border: 0.5px solid #c0ccda;
|
|
|
- border-radius: 2px;
|
|
|
- padding: 16px 16px 16px 16px;
|
|
|
- }
|
|
|
- .concrete-content-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 8px;
|
|
|
- }
|
|
|
- .concrete-content-item a-input {
|
|
|
- flex: 1;
|
|
|
- margin-right: 8px;
|
|
|
- }
|
|
|
- .custom-collapse-tag {
|
|
|
- background-color: #ecf5fc;
|
|
|
- color: #333;
|
|
|
- border-radius: 0px;
|
|
|
- border: none;
|
|
|
- margin: 30px 0 90px 0;
|
|
|
- }
|
|
|
- .custom-collapse-panel {
|
|
|
- border: none !important;
|
|
|
- border-radius: 0px;
|
|
|
- }
|
|
|
- .step-content {
|
|
|
- margin-top: 20px;
|
|
|
- }
|
|
|
- .steps-action {
|
|
|
- margin-top: 20px;
|
|
|
- display: flex;
|
|
|
- justify-content: flex-end;
|
|
|
- gap: 10px;
|
|
|
- }
|
|
|
- .step-style {
|
|
|
- margin: 0 auto;
|
|
|
- width: 60%;
|
|
|
- }
|
|
|
- .custom-step .ant-steps-item-title {
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
- .description {
|
|
|
- width: calc(100% - 90px);
|
|
|
- margin: 0px 0 30px 20px;
|
|
|
- font-size: 14px;
|
|
|
- padding: 10px 15px;
|
|
|
- color: #666;
|
|
|
- background-color: #f9f9f9;
|
|
|
- }
|
|
|
- .description .anticon {
|
|
|
- margin-right: 8px;
|
|
|
- }
|
|
|
- .btn-style {
|
|
|
- margin: 0 15px;
|
|
|
- border-color: #cececd;
|
|
|
- color: #606266;
|
|
|
- }
|
|
|
- .action-btn {
|
|
|
- margin: 0 15px;
|
|
|
- color: #4096ff;
|
|
|
- border-color: #4096ff;
|
|
|
- }
|
|
|
- .btn-style:hover {
|
|
|
- margin: 0 15px;
|
|
|
- border-color: #cececd;
|
|
|
- color: #606266;
|
|
|
- }
|
|
|
- a-textarea {
|
|
|
- width: 100%;
|
|
|
- }
|
|
|
- .highlighted-text {
|
|
|
- color: #1c53d9;
|
|
|
- margin: 0 5px;
|
|
|
- background-color: #e8edfb;
|
|
|
- padding: 3px 5px;
|
|
|
- }
|
|
|
- .custom-collapse {
|
|
|
- background-color: #f3faef;
|
|
|
- color: #333;
|
|
|
- border-radius: 0px;
|
|
|
- border: none;
|
|
|
- margin-top: 20px;
|
|
|
- }
|
|
|
- .tag-collapse-panel {
|
|
|
- border: none;
|
|
|
- }
|
|
|
- .loading-style {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- z-index: 1;
|
|
|
- position: fixed !important;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- background: rgba(255, 255, 255, 0.7);
|
|
|
- // background: yellow;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
- }
|
|
|
- .ant-spin-nested-loading > div > .ant-spin {
|
|
|
- max-height: 100% !important;
|
|
|
- background: rgba(255, 255, 255, 0.7);
|
|
|
- }
|
|
|
- .concrete-content-container .ant-form-item {
|
|
|
- display: contents !important;
|
|
|
- }
|
|
|
- .warning-style {
|
|
|
- color: #ff4949;
|
|
|
- font-size: 12px;
|
|
|
- margin-left: -240px;
|
|
|
- position: absolute;
|
|
|
- bottom: -20px;
|
|
|
- }
|
|
|
+.user-phase-drawer {
|
|
|
+ width: 900px;
|
|
|
+ height: 100vh;
|
|
|
+}
|
|
|
+
|
|
|
+.step-content {
|
|
|
+ margin-top: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.steps-action {
|
|
|
+ margin-top: 20px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.step-style {
|
|
|
+ margin: 0 auto;
|
|
|
+ width: 60%;
|
|
|
+}
|
|
|
+
|
|
|
+.custom-step .ant-steps-item-title {
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.loading-style {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 1;
|
|
|
+ position: fixed !important;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ background: rgba(255, 255, 255, 0.7);
|
|
|
+ // background: yellow;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.ant-spin-nested-loading>div>.ant-spin {
|
|
|
+ max-height: 100% !important;
|
|
|
+ background: rgba(255, 255, 255, 0.7);
|
|
|
+}
|
|
|
+
|
|
|
+.warning-style {
|
|
|
+ color: #ff4949;
|
|
|
+ font-size: 12px;
|
|
|
+ margin-left: -240px;
|
|
|
+ position: absolute;
|
|
|
+ bottom: -20px;
|
|
|
+}
|
|
|
</style>
|