addEditor.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. <template>
  2. <div class="w-full h-full flex flex-col">
  3. <div class="flex-1 overflow-y-auto">
  4. <van-form ref="vanFormRef" show-error :show-error-message="false" label-align="left" input-align="right"
  5. class="bg-white" @submit="onSubmit">
  6. <van-field v-model.trim="vantFormVal.taskName" name="taskName" rows="2" label="任务名称" maxlength="100" required
  7. show-word-limit type="textarea" placeholder="请输入" />
  8. <template v-if="userInfo?.company?.isSimple != 1">
  9. <van-field v-model="vantFormVal.priority" name="priority" label="优先级" placeholder="请选择" is-link readonly
  10. required @click="showSelectionBox('priority', fixedFieldPriority)">
  11. <template #input v-if="vantFormVal.priority || vantFormVal.priority == 0">
  12. {{ vantFormVal.priorityName }}
  13. </template>
  14. </van-field>
  15. <van-field v-model="vantFormVal.taskType" name="taskType" label="任务类型" placeholder="请选择" is-link readonly
  16. @click="showSelectionBox('taskType', fixedFieldTaskType)" class="resetStyles">
  17. <template #input v-if="vantFormVal.taskType || vantFormVal.taskType == 0">
  18. {{ vantFormVal.taskTypeName }}
  19. </template>
  20. </van-field>
  21. <!-- 客户选择 -->
  22. <template v-if="vantFormVal.taskType == 0">
  23. <van-field v-model="vantFormVal.customId" name="customId" label="客户" placeholder="请选择" is-link readonly
  24. @click="showSelectionBox('customId', allCustomersList)" class="resetStyles">
  25. <template #input v-if="vantFormVal.customId">
  26. {{ vantFormVal.customIdName }}
  27. </template>
  28. </van-field>
  29. </template>
  30. <!-- 商机选择 -->
  31. <template v-if="vantFormVal.taskType == 1">
  32. <van-field v-model="vantFormVal.businessOpportunityId" name="businessOpportunityId" :label="`${businessLabel}`"
  33. placeholder="请选择" is-link readonly class="resetStyles"
  34. @click="showSelectionBox('businessOpportunityId', allBusinessOpportunities)">
  35. <template #input v-if="vantFormVal.businessOpportunityId">
  36. {{ vantFormVal.businessOpportunityIdName }}
  37. </template>
  38. </van-field>
  39. </template>
  40. <!-- 销售订单选择 -->
  41. <template v-if="vantFormVal.taskType == 2">
  42. <van-field v-model="vantFormVal.orderId" name="orderId" label="销售订单" placeholder="请选择" is-link readonly
  43. class="resetStyles" @click="showSelectionBox('orderId', allSalesOrdersList)">
  44. <template #input v-if="vantFormVal.orderId">
  45. {{ vantFormVal.orderIdName }}
  46. </template>
  47. </van-field>
  48. </template>
  49. <!-- 线索选择 -->
  50. <template v-if="vantFormVal.taskType == 3">
  51. <van-field v-model="vantFormVal.clueId" name="clueId" label="线索" placeholder="请选择" is-link readonly
  52. class="resetStyles" @click="showSelectionBox('clueId', allCluesList)">
  53. <template #input v-if="vantFormVal.clueId">
  54. {{ vantFormVal.clueIdName }}
  55. </template>
  56. </van-field>
  57. </template>
  58. <van-field v-model="vantFormVal.contactsId" name="contactsId" label="联系人" placeholder="请选择" is-link readonly
  59. :disabled="contactDisabled"
  60. v-if="fixedFieldTaskType.find(v => v.value == (vantFormVal.taskType || '1'))?.show" class="resetStyles"
  61. @click="showSelectionBox('contactsId', allContactsList)">
  62. <template #input v-if="vantFormVal.contactsId">
  63. {{ vantFormVal.contactsIdName }}
  64. </template>
  65. </van-field>
  66. </template>
  67. <van-field v-model="vantFormVal.executorId" name="executorId" label="执行人" placeholder="请选择" is-link readonly
  68. class="resetStyles" @click="showSelectionToBox('executorId')">
  69. <template #input v-if="vantFormVal.executorIdName && vantFormVal.executorIdName.length > 0">
  70. <TranslationComponent :openId="vantFormVal.executorIdName" />
  71. </template>
  72. </van-field>
  73. <van-field name="isRepeat" label="重复提醒" class="resetStyles">
  74. <template #input>
  75. <van-switch v-model="vantFormVal.isRepeat" size="small" />
  76. </template>
  77. </van-field>
  78. <!-- 重复提醒 -->
  79. <template v-if="vantFormVal.isRepeat">
  80. <van-field v-model="vantFormVal.repeatType" name="repeatType" label="重复类型" placeholder="请选择" is-link readonly
  81. class="resetStyles" @click="showSelectionBox('repeatType', fixedFieldRepetitiveType)">
  82. <template #input v-if="vantFormVal.repeatType">
  83. {{ vantFormVal.repeatTypeName }}
  84. </template>
  85. </van-field>
  86. <template v-if="[0, 1, 2, 3, '0', '1', '2', '3'].includes(vantFormVal.repeatType)">
  87. <van-field v-model="vantFormVal.repeatDesignSameday" type="digit" name="repeatDesignSameday" label="每"
  88. class="resetStyles" v-if="vantFormVal.repeatType == 3">
  89. <template #input>
  90. <van-stepper v-model="vantFormVal.repeatDesignSameday" :min="0" button-size="1.2rem" theme="round"
  91. integer class="mr-2" />
  92. </template>
  93. <template #extra> 天 </template>
  94. </van-field>
  95. <van-field name="endType" label="结束" class="resetStyles">
  96. <template #input>
  97. <van-radio-group v-model="vantFormVal.endType" direction="horizontal" class="flex flex-col"
  98. @change="radiogroupChange">
  99. <van-radio name="1"><span
  100. :class="vantFormVal.endType == 1 ? 'themeTextColor' : ''">永不</span></van-radio>
  101. <van-radio name="2" class="mt-3">
  102. <van-stepper v-model="vantFormVal.repeatEndCount" :disabled="vantFormVal.endType != 2" :min="0"
  103. button-size="1.2rem" theme="round" integer class="mr-2" />
  104. 次数以后
  105. </van-radio>
  106. <van-radio name="3" class="mt-3">
  107. <div class="flex items-center">
  108. <van-field label="日期" is-link readonly :disabled="vantFormVal.endType != 3" class="selectField"
  109. placeholder="请选择" @click="vantFormVal.endType == 3 && showDatePickerBox('repeatEndDate')">
  110. <template #input v-if="vantFormVal.repeatEndDate">
  111. {{ vantFormVal.repeatEndDate }}
  112. </template>
  113. </van-field>
  114. 以后
  115. </div>
  116. </van-radio>
  117. </van-radio-group>
  118. </template>
  119. </van-field>
  120. </template>
  121. <template v-if="[4, '4'].includes(vantFormVal.repeatType)">
  122. <div class="flex items-center justify-between px-8 pt-3">
  123. <div>自定义日期</div>
  124. <div><van-icon name="add-o" class="ml-2 themeTextColor" size="1.3rem" @click="addCustomeDateItem()" />
  125. </div>
  126. </div>
  127. <van-cell-group inset class="additionalCoAuthorship">
  128. <template v-for="(item, index) in customeDate">
  129. <van-cell :title="`第${index + 1}次重复在`">
  130. <template #default>
  131. <div class="flex items-center justify-end">
  132. <van-stepper v-model="item.value" :min="0" button-size="1.2rem" theme="round" integer
  133. class="mr-2" />
  134. 天后
  135. <van-icon name="delete-o" class="ml-2 text-[red]" size="1.3rem"
  136. @click="deleteCustomeDateItem(index)" />
  137. </div>
  138. </template>
  139. </van-cell>
  140. </template>
  141. </van-cell-group>
  142. </template>
  143. </template>
  144. <van-field label="开始时间" name="startDate" is-link readonly class="resetStyles" placeholder="请选择"
  145. @click="showDatePickerBox('startDate')">
  146. <template #input v-if="vantFormVal.startDate">
  147. {{ vantFormVal.startDate }}
  148. </template>
  149. </van-field>
  150. <van-field label="结束时间" name="endDate" is-link readonly class="resetStyles" placeholder="请选择"
  151. @click="showDatePickerBox('endDate')">
  152. <template #input v-if="vantFormVal.endDate">
  153. {{ vantFormVal.endDate }}
  154. </template>
  155. </van-field>
  156. <div></div>
  157. </van-form>
  158. <CustomerForm ref="formFormRef" :formJson="formJson" :formValue="formVal"></CustomerForm>
  159. </div>
  160. <div class="mar-20px ">
  161. <van-button type="primary" @click="onSubmit" class="w-full">
  162. {{ Object.keys(formVal).length > 0 ? '确定修改' : '确定添加' }}
  163. </van-button>
  164. </div>
  165. <!-- 选择器 -->
  166. <div>
  167. <!-- 下拉框选择 -->
  168. <van-popup v-model:show="showSelectionFlag" destroy-on-close position="bottom" :style="{ height: '80%' }">
  169. <PullDownSelector :show-element="showSelectionFlag" :options="showSelectionArray" :doYouNeedTranslation="false" @change="selectChange" />
  170. </van-popup>
  171. <van-popup v-model:show="showSelectionToFlag" destroy-on-close position="bottom" :style="{ height: '80%' }">
  172. <PullDownSelector :show-element="showSelectionToFlag" :value="showSelectionToValue" @change="selectChange" :multiple-choice="true" />
  173. </van-popup>
  174. <!-- 选择日期 -->
  175. <van-popup v-model:show="showDatePicker" destroy-on-close position="bottom" :style="{ height: '50%' }">
  176. <van-date-picker v-model="showDatePickerVal" @confirm="showPickerConfirm" @cancel="showDatePicker = false" />
  177. </van-popup>
  178. <!-- 选择时间 -->
  179. <van-popup v-model:show="showDateTimePicker" destroy-on-close position="bottom" :style="{ height: '50%' }">
  180. <van-time-picker v-model="showDatePickerTimeVal" @confirm="showPickerTimeConfirm" @cancel="showDateTimePicker = false" :filter="filterTimePicker" />
  181. </van-popup>
  182. </div>
  183. </div>
  184. </template>
  185. <script setup>
  186. import { ref, onActivated, computed } from 'vue';
  187. import { useLifecycle } from '@hooks/useCommon.js';
  188. import { fixedFieldTaskType, fixedFieldPriority, fixedFieldRepetitiveType } from '@utility/defaultData.js';
  189. import { GET_ALL_CUSTOMERSLIST, GET_ALL_BUSINESS_OPPORTUNITIES, GET_SALES_ORDER_LIST, GET_OBTAIN_ALL_CLUES, GET_CONTACTS_WITH_MORE_I_DS, TASK_ADD_EDIT, MODIFY_TASK } from "@hooks/useApi";
  190. import requests from "@common/requests";
  191. import useToast from "@hooks/useToast"
  192. import dayjs from 'dayjs';
  193. import PullDownSelector from '@components/common/pullDownSelector.vue'
  194. import CustomerForm from '@components/common/formForm/formView.vue'
  195. import TranslationComponent from '@components/common/translationComponent.vue';
  196. import useRouterStore from "@store/useRouterStore.js";
  197. import commonUtil from "@utility/commonUtil"
  198. import useInfoStore from '@store/useInfoStore'
  199. const userInfo = useInfoStore().userInfo
  200. const router = useRouterStore()
  201. const { toastText, toastSuccess, toastFail, toastLoading } = useToast()
  202. const props = defineProps({
  203. formJson: { required: true },
  204. formValue: { required: true },
  205. });
  206. const formFormRef = ref(null)
  207. const vantFormVal = ref({
  208. taskType: 0,
  209. taskTypeName: '客户',
  210. endType: '1',
  211. repeatEndCount: 0,
  212. repeatType: 0,
  213. repeatTypeName: '每天'
  214. })
  215. const formVal = ref({})
  216. const allBusinessOpportunities = ref([])
  217. const allCustomersList = ref([])
  218. const allCluesList = ref([])
  219. const allSalesOrdersList = ref([])
  220. const allContactsList = ref([])
  221. const showSelectionFlag = ref(false)
  222. const showSelectionFiled = ref([])
  223. const showSelectionArray = ref([])
  224. const showDatePicker = ref(false)
  225. const showDateTimePicker = ref(false)
  226. const showDatePickerVal = ref(dayjs().format("YYYY-MM-DD").split("-"))
  227. const showDatePickerTimeVal = ref(dayjs().format("HH:mm").split(":"))
  228. const showDatePickerFiled = ref('')
  229. const customeDate = ref([])
  230. const showSelectionToFlag = ref(false)
  231. const showSelectionToValue = ref([])
  232. const taskTypeFiled = ['customId', 'businessOpportunityId', 'orderId', 'clueId']
  233. const isExistBusiness = sessionStorage.getItem("isExistBusiness");
  234. const businessLabel = isExistBusiness === "1" ? "商机" : "项目";
  235. const contactDisabled = computed(() => {
  236. const taskType = vantFormVal.value?.taskType
  237. if (!taskType && taskType != 0) {
  238. return true
  239. }
  240. if (taskType == 0 && !vantFormVal.value.customId) {
  241. return true
  242. }
  243. if (taskType == 1 && !vantFormVal.value.businessOpportunityId) {
  244. return true
  245. }
  246. if (taskType == 2 && !vantFormVal.value.orderId) {
  247. return true
  248. }
  249. return false
  250. })
  251. function filterTimePicker(type, options) {
  252. if (type === 'minute') {
  253. return options.filter(option => Number(option.value) % 30 === 0);
  254. }
  255. return options;
  256. }
  257. function onSubmit() {
  258. formFormRef.value.getJsonData().then((res) => {
  259. let formValue = {
  260. ...formVal.value,
  261. ...vantFormVal.value,
  262. ...res.data,
  263. repeatDesignDay: customeDate.value.map(item => item.value).join(','),
  264. executorId: vantFormVal.value.executorId,
  265. isRepeat: vantFormVal.value.isRepeat ? 1 : 0,
  266. }
  267. delete formValue.taskLogs
  268. delete formValue.contactsName
  269. delete formValue.orderIdName
  270. delete formValue.priorityName
  271. delete formValue.taskTypeName
  272. delete formValue.repeatTypeName
  273. delete formValue.executorIdName
  274. delete formValue.taskExecutors
  275. console.log('formValue', formValue)
  276. toastLoading('保存中')
  277. const url = formValue.id ? MODIFY_TASK : TASK_ADD_EDIT
  278. requests.post(url, { ...commonUtil.getFromValue({ ...formValue }) }).then(() => {
  279. toastSuccess('保存成功')
  280. setTimeout(() => {
  281. router.navigateBack({
  282. success: () => {
  283. router.eventEmit('moduleListRefreshData', {})
  284. }
  285. })
  286. }, 2000)
  287. }).finally(() => {
  288. })
  289. })
  290. }
  291. function showPickerConfirm({ selectedValues }) {
  292. // vantFormVal.value[showDatePickerFiled.value] = selectedValues.join('-')
  293. // showDatePicker.value = false
  294. if(showDatePickerFiled.value == 'repeatEndDate') {
  295. vantFormVal.value[showDatePickerFiled.value] = selectedValues.join('-')
  296. showDatePicker.value = false
  297. } else {
  298. showDatePicker.value = false
  299. showDateTimePicker.value = true
  300. }
  301. }
  302. function showPickerTimeConfirm({ selectedValues }) {
  303. vantFormVal.value[showDatePickerFiled.value] = `${showDatePickerVal.value.join('-')} ${selectedValues.join(':')}`
  304. showDateTimePicker.value = false
  305. }
  306. function showDatePickerBox(filed) {
  307. console.log(vantFormVal.value[filed], '<==== 123321')
  308. const dateVal = vantFormVal.value[filed] ? vantFormVal.value[filed].split(' ')[0] : dayjs().format("YYYY-MM-DD")
  309. const timeVal = vantFormVal.value[filed] ? vantFormVal.value[filed].split(' ')[1] : dayjs().format("HH:mm")
  310. showDatePickerFiled.value = filed
  311. showDatePickerVal.value = dateVal.split("-")
  312. showDatePickerTimeVal.value = timeVal.split(":")
  313. showDatePicker.value = true
  314. }
  315. function selectChange(value, label) {
  316. console.log(value, label)
  317. if (taskTypeFiled.includes(showSelectionFiled.value)) {
  318. const item = fixedFieldTaskType.find(item => item.value == vantFormVal.value.taskType)
  319. console.log(item, value,)
  320. if (item && item.show) {
  321. getContactData(showSelectionFiled.value, value)
  322. }
  323. }
  324. if (showSelectionFiled.value == 'repeatType') {
  325. vantFormVal.value = {
  326. ...vantFormVal.value,
  327. endType: 0,
  328. repeatEndCount: 0,
  329. repeatEndDate: null
  330. }
  331. customeDate.value = []
  332. }
  333. vantFormVal.value[showSelectionFiled.value] = Array.isArray(value) ? value.join(',') : value
  334. vantFormVal.value[`${showSelectionFiled.value}Name`] = label
  335. showSelectionFlag.value = false
  336. showSelectionToFlag.value = false
  337. }
  338. function showSelectionToBox(filed) {
  339. showSelectionFiled.value = filed
  340. showSelectionToValue.value = vantFormVal.value[filed] || []
  341. showSelectionToFlag.value = true
  342. }
  343. function showSelectionBox(filed, list = [], event) {
  344. if (taskTypeFiled.includes(filed)) {
  345. const fileds = taskTypeFiled.filter(item => item !== filed)
  346. fileds.forEach(item => {
  347. vantFormVal.value[item] = ''
  348. vantFormVal.value[`${item}Name`] = ''
  349. })
  350. vantFormVal.value.contactsId = ''
  351. vantFormVal.value[`contactsIdName`] = ''
  352. }
  353. showSelectionFiled.value = filed
  354. showSelectionArray.value = filed == 'executorId' ? [] : list
  355. showSelectionFlag.value = true
  356. }
  357. function addCustomeDateItem() {
  358. customeDate.value.push({ value: null })
  359. }
  360. function deleteCustomeDateItem(index) {
  361. customeDate.value.splice(index, 1)
  362. }
  363. function radiogroupChange(val) {
  364. switch (val) {
  365. case 1:
  366. vantFormVal.value.repeatEndDate = ''
  367. vantFormVal.value.repeatEndCount = null
  368. break;
  369. case 2:
  370. vantFormVal.value.repeatEndDate = ''
  371. break;
  372. case 3:
  373. vantFormVal.value.repeatEndCount = null
  374. break;
  375. default:
  376. break;
  377. }
  378. }
  379. function getContactData(filed, value) {
  380. const urlType = {
  381. 'customId': 'customerId',
  382. 'businessOpportunityId': 'businessId',
  383. 'orderId': 'salesId',
  384. }
  385. const url = `${GET_CONTACTS_WITH_MORE_I_DS}?${urlType[filed]}=${value}`
  386. requests.get(url).then(({ data = [] }) => {
  387. let list = data.map(item => {
  388. return {
  389. label: item.name,
  390. value: item.id,
  391. }
  392. })
  393. if (!list.length) {
  394. list = [{}]
  395. }
  396. allContactsList.value = list
  397. })
  398. }
  399. function getAllListData() {
  400. requests.post(GET_ALL_CUSTOMERSLIST, {}).then(res => {
  401. allCustomersList.value = res.data.map(item => {
  402. return {
  403. label: item.customName,
  404. value: item.id,
  405. }
  406. })
  407. })
  408. requests.post(GET_ALL_BUSINESS_OPPORTUNITIES, {}).then(res => {
  409. allBusinessOpportunities.value = res.data.map(item => {
  410. return {
  411. label: item.name,
  412. value: item.id,
  413. }
  414. })
  415. })
  416. requests.post(GET_SALES_ORDER_LIST, { pageIndex: -1, pageSize: -1 }).then(({ data }) => {
  417. allSalesOrdersList.value = (data.record || []).map(item => {
  418. return {
  419. label: item.orderName,
  420. value: item.id,
  421. }
  422. })
  423. })
  424. requests.post(GET_OBTAIN_ALL_CLUES, {}).then(res => {
  425. allCluesList.value = res.data.map(item => {
  426. return {
  427. label: item.clueName,
  428. value: item.id,
  429. }
  430. })
  431. })
  432. }
  433. function initializeData() {
  434. const row = props.formValue
  435. if (!row.id) {
  436. vantFormVal.value = {
  437. taskType: 0,
  438. taskTypeName: '客户',
  439. endType: '1',
  440. repeatEndCount: 0,
  441. repeatType: 0,
  442. repeatTypeName: '每天'
  443. }
  444. formVal.value = props.formValue
  445. customeDate.value = []
  446. return
  447. }
  448. const { id, taskName, priority, taskType, customId, customName, businessOpportunityId, businessName, orderId, orderName, clueId, clueName, contactsId, contactsName
  449. , taskExecutors, isRepeat, repeatType, repeatDesignSameday, endType, repeatEndCount, repeatEndDate, repeatDesignDay, executorId, startDate, endDate } = row
  450. vantFormVal.value = {
  451. id, taskName, priority, taskType, customId, businessOpportunityId, orderId, clueId, contactsId, executorId, repeatType, repeatDesignSameday, endType, repeatEndCount, repeatEndDate, startDate, endDate,
  452. isRepeat: isRepeat == 1 ? true : false,
  453. executorIdName: taskExecutors || [],
  454. contactsIdName: contactsName,
  455. clueIdName: clueName,
  456. orderIdName: orderName,
  457. customIdName: customName,
  458. businessOpportunityIdName: businessName,
  459. priorityName: fixedFieldPriority.find(item => item.value == priority)?.label || '',
  460. taskTypeName: fixedFieldTaskType.find(item => item.value == taskType)?.label || '',
  461. repeatTypeName: fixedFieldRepetitiveType.find(item => item.value == repeatType)?.label || ''
  462. }
  463. const list = repeatDesignDay && repeatDesignDay.split(',') || []
  464. customeDate.value = (list || []).map(item => {
  465. return {
  466. value: item
  467. }
  468. })
  469. formVal.value = props.formValue
  470. if ((taskType || taskType == 0) && taskType != 3) {
  471. const filed = taskType == 0 ? 'customId' : taskType == 1 ? 'businessOpportunityId' : taskType == 2 ? 'orderId' : 'clueId'
  472. const value = taskType == 0 ? customId : taskType == 1 ? businessOpportunityId : taskType == 2 ? orderId : clueId
  473. if (value) {
  474. getContactData(filed, value)
  475. }
  476. }
  477. }
  478. useLifecycle({
  479. load: () => {
  480. initializeData()
  481. getAllListData()
  482. },
  483. init: () => {
  484. initializeData()
  485. getAllListData()
  486. }
  487. });
  488. onActivated(() => {
  489. })
  490. </script>
  491. <style lang='scss' scoped>
  492. .selectField {
  493. padding: 0;
  494. width: 12rem;
  495. margin-right: 4px;
  496. }
  497. .selectField :deep(.van-cell__title) {
  498. width: 4rem;
  499. }
  500. .additionalCoAuthorship {
  501. border-bottom: 1px solid #EBEDF0
  502. }
  503. </style>