index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. <template>
  2. <el-dialog v-model="props.visible" width="800px" :show-close="false" :close-on-click-modal="false" top="10vh">
  3. <template #header="{ titleId, titleClass }">
  4. <div class="flex justify-between items-center border-b pb-3">
  5. <h4 :id="titleId" :class="titleClass">{{ title || "新建任务" }}</h4>
  6. <div>
  7. <el-button v-if="!editForm" type="primary" :loading="['2'].includes(props.saveLoading)"
  8. @click="submitForm(formRef, true)">保存并新建</el-button>
  9. <el-button type="primary" :loading="['2'].includes(props.saveLoading)"
  10. @click="submitForm(formRef, false)">保存</el-button>
  11. <el-button @click="closeVisible()">取消</el-button>
  12. </div>
  13. </div>
  14. </template>
  15. <div class="h-[55vh] overflow-y-auto scroll-bar mt-5">
  16. <el-form ref="formRef" :model="form" label-width="7em" :rules="rules" class="flex flex-wrap form">
  17. <el-form-item label="任务名称:" prop="taskName" required>
  18. <el-input v-model="form.taskName" type="textarea" placeholder="请输入任务名称" clearable maxlength="100"
  19. show-word-limit :disabled="disabledList && disabledList.includes('taskName')" />
  20. </el-form-item>
  21. <el-form-item prop="priority" label="优先级:" required>
  22. <el-select v-model="form.priority" placeholder="请选择" clearable
  23. :disabled="disabledList && disabledList.includes('priority')">
  24. <el-option v-for="item in PRIORITY " :key="item.value" :value="item.value" :label="item.label" />
  25. </el-select>
  26. </el-form-item>
  27. <el-form-item :label="form.taskType">
  28. <template #label>
  29. <el-select v-model="form.taskType" class="border resetSelect" style="width: 100px" @change="changeTaskType"
  30. :disabled="disabledList && disabledList.includes('taskType')">
  31. <el-option v-for="item in TASK_TYPE" :key="item.value" :value="item.value" :label="item.label" />
  32. </el-select>
  33. </template>
  34. <template v-for="item in TASK_TYPE_FIELD">
  35. <el-select v-model="form[item.field]" v-if="form.taskType == item.type" placeholder="请选择" clearable
  36. filterable :disabled="disabledList && disabledList.includes(item.field)" @change="(e: any) => {taskFormChange(e, item.field)}">
  37. <el-option v-for="v in taskTypeValueData" :key="v.id" :value="v[item.valueIndex]"
  38. :label="v[item.labelIndex]" />
  39. </el-select>
  40. </template>
  41. </el-form-item>
  42. <el-form-item label="联系人:" v-if="TASK_TYPE.find(v => v.value == (form.taskType || '1'))?.show">
  43. <el-select v-model="form.contactsId" placeholder="请选择" clearable filterable
  44. :disabled="(disabledList && disabledList.includes('contactsId'))">
  45. <el-option v-for="item in contactValueData" :key="item.id" :value="item.id" :label="item.name" />
  46. </el-select>
  47. </el-form-item>
  48. <el-form-item label="执行人:">
  49. <el-select v-model="form.executorId" placeholder="请选择" clearable multiple filterable
  50. :disabled="disabledList && disabledList.includes('executorId')">
  51. <el-option v-for="item in executorValueData" :key="item.id" :value="item.id" :label="item.name" />
  52. </el-select>
  53. </el-form-item>
  54. <el-form-item label="重复提醒:">
  55. <el-switch v-model="form.isRepeat" :active-value="1" :inactive-value="0" @change="changeRepeat" />
  56. </el-form-item>
  57. <template v-if="form.isRepeat === 1">
  58. <el-form-item label="重复类型:">
  59. <el-select v-model="form.repeatType" placeholder="请选择" @change="changeRepeatType">
  60. <el-option v-for="item in REPEAT_TYPE" :key="item.value" :value="item.value" :label="item.label" />
  61. </el-select>
  62. </el-form-item>
  63. <template v-if="[0, 1, 2, 3].includes(form.repeatType)">
  64. <el-form-item label="每:" v-if="form.repeatType == 3">
  65. <el-input-number v-model="form.repeatDesignSameday" controls-position="right" :min="1" />天
  66. </el-form-item>
  67. <el-form-item label="结束:">
  68. <el-radio-group v-model="form.endType" @change="changeEndType">
  69. <el-radio :label="1" class="w-full">永不</el-radio>
  70. <el-radio :label="2" class="w-full mb-3"><el-input-number v-model="form.repeatEndCount" :min="1"
  71. controls-position="right" :disabled="form.endType != 2" />
  72. 次以后
  73. </el-radio>
  74. <el-radio :label="3" class="w-full">
  75. <el-date-picker v-model="form.repeatEndDate" type="date" placeholder="选择日期" style="width:65%"
  76. :disabled-date="(value: Date) => (new Date() > new Date(value))" value-format="YYYY-MM-DD"
  77. :disabled="form.endType != 3" />
  78. 以后
  79. </el-radio>
  80. </el-radio-group>
  81. </el-form-item>
  82. </template>
  83. <template v-if="[4].includes(form.repeatType)">
  84. <el-form-item v-for="(v, i) in customeDate" class="flex justify-between items-center customeDate">
  85. <div>
  86. 第{{ i + 1 }}次重复在
  87. <el-input-number :model-value="Number(v)" controls-position="right" @change="changeDate(i, $event)"
  88. :min="1" />
  89. 天后
  90. </div>
  91. <div>
  92. <el-icon size="24" @click="deleteCustomeDateItem(i)" class=" hover:text-blue-500 cursor-pointer">
  93. <Delete />
  94. </el-icon>
  95. </div>
  96. </el-form-item>
  97. <el-form-item>
  98. <div>
  99. <el-icon size="24" @click="addCustomeDateItem()" class=" hover:text-blue-500 cursor-pointer">
  100. <Plus />
  101. </el-icon>
  102. </div>
  103. </el-form-item>
  104. </template>
  105. </template>
  106. <el-form-item label="开始时间:" class="w50">
  107. <el-date-picker v-model="form.startDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD"
  108. :disabled="disabledList && disabledList.includes('startDate')" />
  109. </el-form-item>
  110. <el-form-item label="截止时间:" class="w50">
  111. <el-date-picker v-model="form.endDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD"
  112. :disabled="disabledList && disabledList.includes('endDate')" />
  113. </el-form-item>
  114. </el-form>
  115. <GenerateForm ref="generateFormRef" :data="generateFormData" :value="form" />
  116. <div v-if="showLog">
  117. <el-form-item label="操作记录" label-width="7em">
  118. <div class="w-full">
  119. <div v-for="item in form.taskLogs" class=" border-b-2 w-full pl-3">
  120. {{ `${dayjs(item.modTime).format('YYYY-MM-DD HH:mm:ss')} ${item.userName} ${item.content}` }}
  121. </div>
  122. </div>
  123. </el-form-item>
  124. </div>
  125. </div>
  126. </el-dialog>
  127. </template>
  128. <script lang="ts" setup>
  129. import { ref, watch } from 'vue';
  130. import { PRIORITY, TASK_TYPE, TASK_TYPE_FIELD, defalutModalForm, REPEAT_TYPE, CUSTOMER_FORM_URL, defaultGenerateFormData, ALL_CUSTOM, ALL_CLUE, ALL_BUSINESS, ALL_CONTACTS, ALL_ORDERS, ALL_USERS, getTaskType } from "./api";
  131. import { GenerateForm } from "@zmjs/form-design"
  132. import { get, post } from '@/utils/request';
  133. import { Delete, Plus } from "@element-plus/icons-vue"
  134. import { FormInstance, dayjs } from 'element-plus';
  135. import { getFromValue } from '@/utils/tools';
  136. import { Props, Emits } from './type';
  137. import { URL_GETALL } from '@/pages/contacts/api';
  138. const props = defineProps<Props>()
  139. const emits = defineEmits<Emits>();
  140. watch(() => props.saveLoading, (val) => {
  141. if (val == "3") {
  142. formRef.value?.resetFields();
  143. form.value = { ...defalutModalForm };
  144. generateFormRef.value?.reset();
  145. taskTypeValueData.value = customeData.value
  146. }
  147. })
  148. watch(() => props.visible, (val) => {
  149. if (val) {
  150. get(CUSTOMER_FORM_URL).then(res => {
  151. if (Array.isArray(res.data) && res.data.length > 0) {
  152. generateFormData.value = JSON.parse(res.data[0].config)
  153. }
  154. })
  155. }
  156. })
  157. const customeData = ref<any>([])
  158. const businessData = ref<any>([])
  159. const orderData = ref<any>([])
  160. const clueData = ref<any>([])
  161. watch(() => props.editForm, (val) => {
  162. let taskType = 0;
  163. if (val) {
  164. taskType = getTaskType(val);
  165. }
  166. get(ALL_CUSTOM, {}).then(({ data }) => {
  167. customeData.value = data;//客户
  168. if (taskType == 0) {
  169. taskTypeValueData.value = data;
  170. }
  171. })
  172. get(ALL_BUSINESS, {}).then(({ data }) => {
  173. businessData.value = data;//商机
  174. if (taskType == 1) {
  175. taskTypeValueData.value = data;
  176. }
  177. })
  178. post(ALL_ORDERS, { pageIndex: -1, pageSize: -1 }).then(({ data }) => {
  179. orderData.value = data.record;//销售订单
  180. if (taskType == 2) {
  181. taskTypeValueData.value = data.record;
  182. }
  183. })
  184. get(ALL_CLUE, {}).then(({ data }) => {
  185. clueData.value = data;//线索
  186. if (taskType == 3) {
  187. taskTypeValueData.value = data;
  188. }
  189. })
  190. get(ALL_CONTACTS, {}).then(({ data }) => {
  191. contactValueData.value = data;//联系人
  192. })
  193. get(ALL_USERS, {}).then(({ data }) => {
  194. executorValueData.value = data;
  195. })
  196. if (val) {
  197. form.value = {
  198. ...val,
  199. taskType,
  200. }
  201. } else {
  202. form.value = { ...defalutModalForm }
  203. }
  204. })
  205. const rules = ref({
  206. taskName: [
  207. { required: true, message: '请输入任务名称', trigger: 'blur' }
  208. ],
  209. priority: [
  210. { required: true, message: '请选择优先级', trigger: 'change' }
  211. ]
  212. })
  213. const form = ref<any>({});
  214. const formRef = ref<FormInstance>();
  215. const generateFormRef = ref<InstanceType<typeof GenerateForm>>();
  216. const generateFormData = ref<any>({ ...defaultGenerateFormData });
  217. function taskFormChange(e: any, field: 'customId' | 'businessOpportunityId' | 'orderId' | 'clueId') {
  218. const fieldMap = {
  219. 'customId': 'customerId',
  220. 'businessOpportunityId': 'businessId',
  221. 'orderId': 'salesId',
  222. 'clueId': ''
  223. };
  224. let fieldStr = fieldMap[field] || '';
  225. updateContactPerson(e, fieldStr)
  226. }
  227. function updateContactPerson(val: any, field: string) {
  228. let formVal = field ? { [field]: val } : {}
  229. get(URL_GETALL, { ...formVal }).then(({ data }) => {
  230. contactValueData.value = data;//联系人
  231. })
  232. }
  233. function closeVisible() {
  234. formRef.value?.resetFields();
  235. generateFormData.value = { ...defaultGenerateFormData };
  236. generateFormRef.value?.reset()
  237. emits('close')
  238. }
  239. function submitForm(formEl: FormInstance | undefined, isClose: boolean) {
  240. if (!formEl) return
  241. formEl.validate((valid: boolean) => {
  242. if (!valid) {
  243. return false as any
  244. }
  245. const repeatDesignDay = customeDate.value.join(",")
  246. generateFormRef.value?.getData().then((res: any) => {
  247. console.log(`{
  248. ...form.value,
  249. repeatDesignDay,
  250. ...res
  251. }`, {
  252. ...form.value,
  253. repeatDesignDay,
  254. ...res
  255. });
  256. let submitData = getFromValue({
  257. ...form.value,
  258. repeatDesignDay,
  259. ...res
  260. })
  261. emits('submit', submitData, isClose)
  262. }).catch((err: any) => {
  263. console.log(err);
  264. })
  265. })
  266. }
  267. const taskTypeValueData = ref<any>([])
  268. function changeTaskType(value: TASK_VALUE_TYPE) {
  269. form.value = {
  270. ...form.value,
  271. taskType: value,
  272. customId: null, // 客户id 0
  273. businessOpportunityId: null, //商机id 1
  274. orderId: null, // 订单id 2
  275. clueId: null, //线索id 3
  276. contactsId: null, //联系人id
  277. }
  278. switch (value) {
  279. case 0:
  280. taskTypeValueData.value = [];
  281. setTimeout(() => {
  282. taskTypeValueData.value = customeData.value;
  283. }, 500)
  284. break;
  285. case 1:
  286. taskTypeValueData.value = [];
  287. setTimeout(() => {
  288. taskTypeValueData.value = businessData.value;
  289. }, 500)
  290. break;
  291. case 2:
  292. taskTypeValueData.value = [];
  293. setTimeout(() => {
  294. taskTypeValueData.value = orderData.value
  295. }, 500)
  296. break;
  297. case 3:
  298. taskTypeValueData.value = [];
  299. setTimeout(() => {
  300. taskTypeValueData.value = clueData.value;
  301. }, 500)
  302. break;
  303. default:
  304. const _n: never = value;
  305. break;
  306. }
  307. }
  308. const contactValueData = ref<any>([])
  309. const executorValueData = ref<any>([])
  310. function changeRepeat(value: string | number | boolean) {
  311. form.value = {
  312. ...form.value,
  313. isRepeat: value,
  314. repeatType: 0, //重复类型
  315. endType: 1, //结束类型
  316. repeatEndNever: 1,
  317. repeatEndCount: null, //重复指定次数次数后结束
  318. repeatEndDate: null, //重复到指定日期后结束
  319. repeatDesignDay: null, //自定义日期
  320. repeatDesignSameday: null, //自定义周期
  321. }
  322. customeDate.value = [];
  323. }
  324. function changeRepeatType(value: REPEAT_VALUE_TYPE) {
  325. form.value = {
  326. ...form.value,
  327. repeatType: value, //重复类型
  328. endType: 1, //结束类型
  329. repeatEndNever: 1,
  330. repeatEndCount: null, //重复指定次数次数后结束
  331. repeatEndDate: null, //重复到指定日期后结束
  332. repeatDesignDay: null, //自定义日期
  333. repeatDesignSameday: null, //自定义周期
  334. }
  335. customeDate.value = [];
  336. }
  337. function changeEndType(value: string | number | boolean | undefined) {
  338. form.value = {
  339. ...form.value,
  340. endType: value, //重复类型
  341. repeatEndNever: value == 1 ? 1 : null,//永不结束
  342. repeatEndCount: null, //重复指定次数次数后结束
  343. repeatEndDate: null, //重复到指定日期后结束
  344. repeatDesignDay: null, //自定义日期
  345. }
  346. }
  347. const customeDate = ref<any>([])
  348. function changeDate(index: number, value: number | undefined) {
  349. customeDate.value[index] = value;
  350. }
  351. function deleteCustomeDateItem(index: number) {
  352. customeDate.value = customeDate.value.filter((_item: number, i: number) => i !== index);
  353. }
  354. function addCustomeDateItem() {
  355. customeDate.value.push(undefined)
  356. }
  357. </script>
  358. <style lang="scss">
  359. .resetSelect {
  360. border: 0;
  361. .el-select__wrapper {
  362. box-shadow: none;
  363. padding-right: 0;
  364. }
  365. .el-select__selected-item {
  366. text-align: right;
  367. }
  368. }
  369. .customeDate {
  370. .el-form-item__content {
  371. justify-content: space-between;
  372. }
  373. }
  374. .el-form-item {
  375. width: 100%;
  376. }
  377. .form {
  378. .w50 {
  379. @apply w-1/2;
  380. }
  381. }
  382. </style>