sopUserLogsInfoDetails.vue 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  1. <template>
  2. <div class="app-container">
  3. <el-alert
  4. title="注意事项"
  5. type="warning"
  6. description="搜索【客户备注】【标签】 只能搜索/筛选出 【当前页】的数据)"
  7. :closable="false"
  8. show-icon>
  9. </el-alert>
  10. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
  11. <!-- <el-form-item label="企微员工账号" prop="qwUserId">-->
  12. <!-- <el-input-->
  13. <!-- v-model="queryParams.qwUserId"-->
  14. <!-- placeholder="请输入企微员工账号"-->
  15. <!-- clearable-->
  16. <!-- size="small"-->
  17. <!-- @keyup.enter.native="handleQuery"-->
  18. <!-- />-->
  19. <!-- </el-form-item>-->
  20. <el-form-item label="客户名称" prop="externalUserName">
  21. <el-input
  22. v-model="queryParams.externalUserName"
  23. placeholder="请输入客户名称"
  24. clearable
  25. size="small"
  26. @keyup.enter.native="handleQuery"
  27. />
  28. </el-form-item>
  29. <el-form-item label="客户备注" prop="remark">
  30. <el-input
  31. v-model="queryParams.remark"
  32. placeholder="请输入客户备注"
  33. clearable
  34. size="small"
  35. @keyup.enter.native="handleQuery"
  36. />
  37. </el-form-item>
  38. <el-form-item label="标签" prop="tagIds">
  39. <!-- <el-select v-model="selectTags" remote multiple placeholder="请选择" filterable style="width: 100%;">-->
  40. <!-- <el-option-->
  41. <!-- v-for="dict in tagList"-->
  42. <!-- :label="dict.name"-->
  43. <!-- :value="dict.tagId">-->
  44. <!-- </el-option>-->
  45. <!-- </el-select>-->
  46. <div @click="hangleChangeTags()" style="cursor: pointer; border: 1px solid #e6e6e6; background-color: white; overflow: hidden; flex-grow: 1;width: 250px">
  47. <div style="min-height: 35px; max-height: 200px; overflow-y: auto;">
  48. <el-tag type="success"
  49. closable
  50. :disable-transitions="false"
  51. v-for="list in this.selectTags"
  52. :key="list.tagId"
  53. @close="handleCloseTags(list)"
  54. style="margin: 3px;"
  55. >{{list.name}}
  56. </el-tag>
  57. </div>
  58. </div>
  59. </el-form-item>
  60. <el-form-item>
  61. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  62. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  63. </el-form-item>
  64. </el-form>
  65. <el-row :gutter="10" class="mb8">
  66. <el-col :span="1.5">
  67. <el-button
  68. type="warning"
  69. icon="el-icon-s-promotion"
  70. size="medium"
  71. :disabled="multiple"
  72. @click="handleSendMsg"
  73. v-hasPermi="['qw:sopUserLogsInfo:msg']"
  74. >一键群发</el-button>
  75. </el-col>
  76. <el-col :span="1.5">
  77. <el-button
  78. type="danger"
  79. plain
  80. icon="el-icon-delete"
  81. size="medium"
  82. :disabled="multiple"
  83. @click="handleUpdate"
  84. v-if="queryParams.filterMode == 1"
  85. v-hasPermi="['qw:sopUserLogsInfo:edit']"
  86. >批量修改客户营期</el-button>
  87. </el-col>
  88. <!-- <el-col :span="1.5">-->
  89. <!-- <el-button-->
  90. <!-- type="success"-->
  91. <!-- plain-->
  92. <!-- icon="el-icon-download"-->
  93. <!-- size="mini"-->
  94. <!-- :loading="exportLoading"-->
  95. <!-- @click="handleExport"-->
  96. <!-- v-hasPermi="['qw:sop:export']"-->
  97. <!-- >导出</el-button>-->
  98. <!-- </el-col>-->
  99. </el-row>
  100. <el-table border v-loading="loading" :data="sopUserLogsInfoList" @selection-change="handleSelectionChange" v-if="queryParams.filterMode == 1">
  101. <el-table-column type="selection" width="55" align="center" />
  102. <el-table-column label="编号" align="center" prop="id" width="100"/>
  103. <!-- <el-table-column label="企微员工账号" align="center" prop="qwUserId" width="100"/>-->
  104. <el-table-column label="客户ID" align="center" prop="externalId" width="100"/>
  105. <!-- <el-table-column label="客户小程序id" align="center" prop="fsUserId" width="100">-->
  106. <!-- <template slot-scope="scope">-->
  107. <!-- <el-tag type="success">-->
  108. <!-- {{ scope.row.fsUserId === 0 || scope.row.fsUserId === null ? '无' : scope.row.fsUserId }}-->
  109. <!-- </el-tag>-->
  110. <!-- </template>-->
  111. <!-- </el-table-column>-->
  112. <el-table-column label="客户名称" align="center" prop="externalUserName" />
  113. <el-table-column label="备注" align="center" prop="remark" />
  114. <el-table-column label="客户标签" align="center" prop="tagIds" width="240">
  115. <template slot-scope="scope">
  116. <div v-for="name in scope.row.tagIdsName" v-if="scope.row.tagIdsName && scope.row.tagIdsName.length > 0 && scope.row.tagIdsName[0] != '无标签'" style="display: inline;">
  117. <el-tag type="success">{{ name }}</el-tag>
  118. </div>
  119. <div v-else>
  120. <span style="color: red;">无标签</span>
  121. </div>
  122. </template>
  123. </el-table-column>
  124. <el-table-column label="进线时间" align="center" prop="inComTime" width="180"/>
  125. <el-table-column label="添加日期" align="center" prop="createTime" width="180"/>
  126. <el-table-column label="添加时间" align="center" prop="crtTime" width="180"/>
  127. <el-table-column label="修改时间" align="center" prop="updateTime" width="180"/>
  128. <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120" fixed="right">
  129. <template slot-scope="scope">
  130. <!-- <el-button-->
  131. <!-- size="mini"-->
  132. <!-- type="text"-->
  133. <!-- icon="el-icon-edit"-->
  134. <!-- @click="handleUpdate(scope.row)"-->
  135. <!-- v-hasPermi="['qw:sopUserLogsInfo:edit']"-->
  136. <!-- >修改客户营期</el-button>-->
  137. <el-button
  138. size="mini"
  139. type="text"
  140. icon="el-icon-delete"
  141. @click="handleDelete(scope.row)"
  142. v-hasPermi="['qw:sopUserLogsInfo:remove']"
  143. >删除客户营期</el-button>
  144. </template>
  145. </el-table-column>
  146. </el-table>
  147. <el-table border v-loading="loading" :data="sopUserLogsInfoList" @selection-change="handleSelectionChange" v-if="queryParams.filterMode == 2">
  148. <el-table-column type="selection" width="55" align="center" />
  149. <el-table-column label="编号" align="center" prop="id" width="100"/>
  150. <el-table-column label="客户名称" align="center" prop="name" />
  151. <el-table-column label="备注" align="center" prop="remark" />
  152. <el-table-column label="客户标签" align="center" prop="tagIds" width="240">
  153. <template slot-scope="scope">
  154. <div v-for="name in scope.row.tagNames" v-if="scope.row.tagNames && scope.row.tagNames.length > 0 && scope.row.tagNames[0] != '无标签'" style="display: inline;">
  155. <el-tag type="success">{{ name }}</el-tag>
  156. </div>
  157. <div v-else>
  158. <span style="color: red;">无标签</span>
  159. </div>
  160. </template>
  161. </el-table-column>
  162. <el-table-column label="加群时间" align="center" prop="joinTime" width="180"/>
  163. <el-table-column label="进线时间" align="center" prop="inComTime" width="180"/>
  164. </el-table>
  165. <pagination-more
  166. v-show="total>0"
  167. :total="total"
  168. :page.sync="queryParams.pageNum"
  169. :limit.sync="queryParams.pageSize"
  170. @pagination="getList"
  171. />
  172. <el-dialog :title="sendMsgOpen.title" :visible.sync="sendMsgOpen.open" width="1000px" append-to-body>
  173. <el-form ref="msgForm" :model="msgForm" :rules="msgRules" label-width="100px">
  174. <el-form-item label="选择课程">
  175. <el-select v-model="msgForm.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini" remote filterable @change="courseChange()">
  176. <el-option
  177. v-for="dict in courseList"
  178. :key="dict.dictValue"
  179. :label="dict.dictLabel"
  180. :value="parseInt(dict.dictValue)"
  181. />
  182. </el-select>
  183. <el-select v-model="msgForm.videoId" placeholder="请选择小节" size="mini" style=" margin-right: 10px;" remote filterable @change="videoIdChange()" >
  184. <el-option
  185. v-for="dict in videoList"
  186. :key="dict.dictValue"
  187. :label="dict.dictLabel"
  188. :value="parseInt(dict.dictValue)"
  189. />
  190. </el-select>
  191. <el-select v-model="msgForm.courseType" placeholder="请选择消息类型" size="mini" style=" margin-right: 10px;">
  192. <el-option
  193. v-for="dict in sysFsSopWatchStatus"
  194. :key="dict.dictValue"
  195. :label="dict.dictLabel"
  196. :value="parseInt(dict.dictValue)"
  197. />
  198. </el-select>
  199. </el-form-item>
  200. <el-form-item label="规则" prop="setting" >
  201. <div v-for="(item, index) in setting" :key="index" style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
  202. <el-row>
  203. <el-col :span="22">
  204. <el-form :model="item" label-width="70px">
  205. <el-form-item label="内容类别" style="margin: 2%">
  206. <el-radio-group v-model="item.contentType">
  207. <el-radio :label="item.dictValue" v-for="item in sysQwSopAiContentType" @change="handleContentTypeChange()">{{item.dictLabel}}</el-radio>
  208. </el-radio-group>
  209. </el-form-item>
  210. <el-form-item label="内容" style="margin-bottom: 2%" >
  211. <el-input
  212. v-if="item.contentType == 1"
  213. v-model="item.value"
  214. type="textarea"
  215. :rows="3"
  216. placeholder="内容"
  217. style="width: 90%; margin-top: 10px;"
  218. @keydown.native="handleKeydown($event, index)"
  219. :ref="`textarea-${index}`"
  220. >
  221. </el-input>
  222. <el-link
  223. v-if="item.contentType == 1"
  224. type="primary"
  225. @click="toggleSalesCall(index)"
  226. style="margin-top: 10px;"
  227. >
  228. {{ item.isSalesCallAdded ? '移除#销售称呼#' : '添加#销售称呼#' }}
  229. </el-link>
  230. <el-link
  231. v-if="item.contentType == 1"
  232. type="primary"
  233. @click="toggleSalesCallCustomer(index)"
  234. style="margin-top: 10px;margin-left: 2%"
  235. >
  236. {{ item.isSalesCallCustomerAdded ? '移除#客户称呼#' : '添加#客户称呼#' }}
  237. </el-link>
  238. <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1" :width="150" :height="150" />
  239. <div v-if="item.contentType == 3 || item.contentType ==9 ">
  240. <el-card class="box-card">
  241. <el-form-item label="链接标题:" label-width="100px">
  242. <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
  243. </el-form-item>
  244. <el-form-item label="链接描述:" label-width="100px" >
  245. <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述" style="width: 90%;margin-top: 1%;"/>
  246. </el-form-item>
  247. <el-form-item label="链接封面:" label-width="100px">
  248. <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
  249. </el-form-item>
  250. <el-form-item label="链接地址:" label-width="100px" >
  251. <el-tag type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
  252. </el-form-item>
  253. </el-card>
  254. </div>
  255. <div v-if="item.contentType == 4">
  256. <el-card class="box-card">
  257. <el-form-item label="标题" prop="miniprogramTitle">
  258. <el-input v-model="item.miniprogramTitle" placeholder="请输入小程序消息标题,最长为64字" />
  259. </el-form-item>
  260. <el-form-item label="封面" prop="miniprogramPicUrl">
  261. <ImageUpload v-model="item.miniprogramPicUrl" type="image" :num="10" :width="150" :height="150" />
  262. </el-form-item>
  263. <el-form-item label="appid" prop="miniprogramAppid" v-show="false" >
  264. <el-input v-model="item.miniprogramAppid='wx73f85f8d62769119' " disabled />
  265. </el-form-item>
  266. <el-form-item label="page路径" prop="miniprogramPage" v-show="false" label-width="100px" style="margin-left: -30px" >
  267. <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径" disabled />
  268. </el-form-item>
  269. </el-card>
  270. </div>
  271. <div v-if="item.contentType == 5 ">
  272. <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
  273. <el-upload
  274. v-model="item.fileUrl"
  275. class="avatar-uploader"
  276. :action="uploadUrl"
  277. :show-file-list="false"
  278. :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
  279. :before-upload="beforeAvatarUploadFile">
  280. <i class="el-icon-plus avatar-uploader-icon"></i>
  281. </el-upload>
  282. <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
  283. {{item.fileUrl}}
  284. </el-link>
  285. </el-form-item>
  286. </div>
  287. <div v-if="item.contentType == 6 ">
  288. <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
  289. <el-upload
  290. v-model="item.videoUrl"
  291. class="avatar-uploader"
  292. :action="uploadUrl"
  293. :show-file-list="false"
  294. :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
  295. :before-upload="beforeAvatarUploadVideo">
  296. <i class="el-icon-plus avatar-uploader-icon"></i>
  297. </el-upload>
  298. <video v-if="item.videoUrl"
  299. :src="item.videoUrl"
  300. controls style="width: 200px;height: 100px">
  301. </video>
  302. </el-form-item>
  303. </div>
  304. <div v-if="item.contentType == 7 ">
  305. <el-input
  306. v-model="item.value"
  307. type="textarea" :rows="3" maxlength="66" show-word-limit
  308. placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
  309. @input="handleInputVideoText(item.value,item)"/>
  310. </div>
  311. <div v-if="item.contentType == 8">
  312. </div>
  313. </el-form-item>
  314. <el-form-item label="添加短链" v-if="item.contentType == 1 " >
  315. <el-tooltip content="请先根据课程选定课程小节之后再添加" effect="dark" :disabled="!!msgForm.videoId">
  316. <el-switch
  317. v-model="item.isBindUrl"
  318. :disabled="!msgForm.videoId"
  319. active-color="#13ce66"
  320. inactive-color="#DCDFE6"
  321. active-value="1"
  322. inactive-value="2">
  323. </el-switch>
  324. </el-tooltip>
  325. <span v-if="item.isBindUrl == '1'" style="margin-left: 10px; color: #13ce66">添加URL</span>
  326. <span v-if="item.isBindUrl == '2'" style="margin-left: 10px; color: #b1b4ba">不加URL</span>
  327. </el-form-item>
  328. <el-form-item label="课节过期时间" v-if="item.isBindUrl == '1'
  329. && item.contentType != 2
  330. && item.contentType != 5
  331. && item.contentType != 6
  332. && item.contentType != 8"
  333. style="margin-top: 1%" label-width="100px">
  334. <el-row>
  335. <el-input-number v-model="item.expiresDays" :min="1" :max="100" ></el-input-number>
  336. (天)
  337. </el-row>
  338. <el-row>
  339. <span class="tip">填写0或不填时,默认为系统配置的默认时间</span>
  340. </el-row>
  341. </el-form-item>
  342. </el-form>
  343. </el-col>
  344. <el-col :span="1" :offset="1">
  345. <i class="el-icon-delete" @click="delSetList(index)" style="margin-top: 20px;" v-if="setting.length>1"></i>
  346. </el-col>
  347. </el-row>
  348. </div>
  349. <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList()' >添加内容</el-link>
  350. </el-form-item>
  351. </el-form>
  352. <div slot="footer" class="dialog-footer">
  353. <el-button type="primary" @click="submitMsgForm">确 定</el-button>
  354. <el-button @click="cancelMsgForm">取 消</el-button>
  355. </div>
  356. </el-dialog>
  357. <!-- 添加或修改sopUserLogsInfo对话框 -->
  358. <el-dialog title="批量修改客户营期" :visible.sync="updateOpen" width="500px" append-to-body>
  359. <el-form ref="updateLogsInfoFrom" :model="updateLogsInfoFrom" :rules="batchRules" label-width="120px">
  360. <el-form-item label="选择营期时间" prop="paramTime">
  361. <el-date-picker clearable size="small"
  362. v-model="updateLogsInfoFrom.paramTime"
  363. type="date"
  364. value-format="yyyy-MM-dd"
  365. placeholder="选择营期时间">
  366. </el-date-picker>
  367. </el-form-item>
  368. </el-form>
  369. <div slot="footer" class="dialog-footer">
  370. <el-button type="primary" @click="submitForm">确 定</el-button>
  371. <el-button @click="cancel">取 消</el-button>
  372. </div>
  373. </el-dialog>
  374. <!-- 搜索标签 -->
  375. <el-dialog :title="changeTagDialog.title" :visible.sync="changeTagDialog.open" style="width:100%;height: 100%" append-to-body>
  376. <div>搜索标签:
  377. <el-input v-model="queryTagParams.name" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
  378. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(queryTagParams.name)">搜索</el-button>
  379. <el-button type="primary" icon="el-icon-plus" size="mini" @click="cancelSearchTags">重置</el-button>
  380. </div>
  381. <div v-for="item in tagGroupList" :key="item.id" >
  382. <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
  383. <span class="name-background">{{ item.name }}</span>
  384. </div>
  385. <div class="tag-container">
  386. <a
  387. v-for="tagItem in item.tag"
  388. class="tag-box"
  389. @click="tagSelection(tagItem)"
  390. :class="{ 'tag-selected': tagItem.isSelected }"
  391. >
  392. {{ tagItem.name }}
  393. </a>
  394. </div>
  395. </div>
  396. <pagination
  397. v-show="tagTotal>0"
  398. :total="tagTotal"
  399. :page.sync="queryTagParams.pageNum"
  400. :limit.sync="queryTagParams.pageSize"
  401. @pagination="getPageListTagGroup"
  402. />
  403. <div slot="footer" class="dialog-footer">
  404. <el-button type="primary" @click="tagSubmitForm()">确 定</el-button>
  405. <el-button @click="tagCancel()">取消</el-button>
  406. </div>
  407. </el-dialog>
  408. </div>
  409. </template>
  410. <script>
  411. import {
  412. listSopUserLogsInfo,
  413. delSopUserLogsInfo,
  414. addSopUserLogsInfo,
  415. updateSopUserLogsInfo,
  416. exportSopUserLogsInfo,
  417. sendMsgSop, batchUpdateSopUserLogsInfoToTime
  418. } from "@/api/qw/sopUserLogsInfo";
  419. import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
  420. import {courseList, videoList} from "@/api/qw/sop";
  421. import {addCourseFinishTemp, updateCourseFinishTemp} from "@/api/course/courseFinishTemp";
  422. import {allListTagGroup} from "@/api/qw/tagGroup";
  423. import {listTag} from "@/api/qw/tag";
  424. import {searchTags} from "../../../api/qw/tag";
  425. export default {
  426. name: "sopUserLogsInfoDetails",
  427. components: {ImageUpload},
  428. data() {
  429. return {
  430. //上传语音的遮罩层
  431. voiceLoading :false,
  432. uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
  433. uploadUrlByVoice:process.env.VUE_APP_BASE_API+"/common/uploadOSSByHOOKVoice",
  434. // 遮罩层
  435. loading: true,
  436. // 导出遮罩层
  437. exportLoading: false,
  438. // 选中数组
  439. ids: [],
  440. // 非单个禁用
  441. single: true,
  442. // 非多个禁用
  443. multiple: true,
  444. // 显示搜索条件
  445. showSearch: true,
  446. // 总条数
  447. total: 0,
  448. // sopUserLogsInfo表格数据
  449. sopUserLogsInfoList: [],
  450. sysFsSopWatchStatus: [],
  451. isSalesCallAdded:false,
  452. isSalesCallCustomerAdded:false,
  453. selectTags:[],
  454. // 弹出层标题
  455. title: "",
  456. // 是否显示弹出层
  457. open: false,
  458. updateOpen:false,
  459. // 查询参数
  460. queryParams: {
  461. pageNum: 1,
  462. pageSize: 10,
  463. tagIds:null,
  464. remark:null,
  465. sopId: null,
  466. userLogsId: null,
  467. userIdParam:null,
  468. startTimeParam:null,
  469. externalContactId: null,
  470. qwUserId: null,
  471. corpId: null,
  472. externalId: null,
  473. fsUserId: null,
  474. externalUserName: null,
  475. createTime: null,
  476. },
  477. tagGroupList: [],
  478. tagTotal:0,
  479. //标签
  480. changeTagDialog:{
  481. title:"",
  482. open:false,
  483. },
  484. queryTagParams:{
  485. pageNum: 1,
  486. pageSize: 10,
  487. total:0,
  488. name:null,
  489. corpId:null,
  490. },
  491. courseList:[],
  492. videoList:[],
  493. //插件版
  494. sysQwSopAiContentType:[],
  495. sendMsgOpen:{
  496. title:'一键批量群发',
  497. open:false,
  498. ids:null,
  499. },
  500. // 表单参数
  501. form: {},
  502. updateLogsInfoFrom:{},
  503. setting:[{contentType:'1', value: '',}],
  504. msgForm:{
  505. videoId:null,
  506. courseId:null,
  507. courseType:null,
  508. userIdParam:null,
  509. setting:null,
  510. ids:null,
  511. sopId: null,
  512. startTime: null,
  513. },
  514. // 表单校验
  515. rules: {},
  516. batchRules:{
  517. paramTime: [
  518. { required: true, message: '选择的时间不能为空', trigger: 'blur' }
  519. ],
  520. },
  521. msgRules:{},
  522. };
  523. },
  524. created() {
  525. this.getDicts("sys_qwSopAi_contentType").then(response => {
  526. this.sysQwSopAiContentType = response.data;
  527. });
  528. this.getDicts("sys_fs_sop_watch_status").then(response => {
  529. this.sysFsSopWatchStatus = response.data;
  530. });
  531. courseList().then(response => {
  532. this.courseList = response.list;
  533. });
  534. },
  535. methods: {
  536. selectSopUserLogsInfo(val,externalUserName){
  537. this.loading = true;
  538. this.queryParams.sopId=val.sopId;
  539. this.queryParams.filterMode=val.filterMode;
  540. this.queryParams.userLogsId=val.id;
  541. this.queryParams.chatId=val.chatId;
  542. if (externalUserName!=null){
  543. this.queryParams.externalUserName = externalUserName;
  544. }
  545. listSopUserLogsInfo(this.queryParams).then(response => {
  546. this.sopUserLogsInfoList = response.rows;
  547. this.total = response.total;
  548. this.loading = false;
  549. });
  550. this.queryParams.qwUserId=val.qwUserId;
  551. this.queryParams.corpId=val.corpId;
  552. //用于一键群发
  553. this.queryParams.userIdParam=val.userId;
  554. this.queryParams.startTimeParam=val.startTime;
  555. this.queryParams.corpIdParam=val.corpId;
  556. },
  557. //搜索的标签
  558. hangleChangeTags(){
  559. this.changeTagDialog.title="搜索的标签"
  560. this.changeTagDialog.open=true;
  561. // 获取 tagListFormIndex 中的所有 tagId,用于快速查找
  562. const selectedTagIds = new Set(
  563. (this.selectTags || []).map(tagItem => tagItem?.tagId)
  564. );
  565. this.queryTagParams.name=null;
  566. this.getPageListTagGroup();
  567. setTimeout(() => {
  568. for (let i = 0; i < this.tagGroupList.length; i++) {
  569. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  570. this.tagGroupList[i].tag[x].isSelected = selectedTagIds.has(this.tagGroupList[i].tag[x].tagId);
  571. }
  572. }
  573. }, 200);
  574. },
  575. tagSelection(row){
  576. row.isSelected= !row.isSelected;
  577. this.$forceUpdate();
  578. },
  579. //确定选择标签
  580. tagSubmitForm(){
  581. for (let i = 0; i < this.tagGroupList.length; i++) {
  582. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  583. if (this.tagGroupList[i].tag[x].isSelected === true) {
  584. if (!this.selectTags) {
  585. this.selectTags = [];
  586. }
  587. // 检查当前 tag 是否已经存在于 tagListFormIndex[index] 中
  588. let tagExists = this.selectTags.some(
  589. tag => tag.id === this.tagGroupList[i].tag[x].id
  590. );
  591. // 如果 tag 不存在于 tagListFormIndex[index] 中,则新增
  592. if (!tagExists) {
  593. this.selectTags.push(this.tagGroupList[i].tag[x]);
  594. }
  595. }
  596. }
  597. }
  598. if (!this.selectTags || this.selectTags.length === 0) {
  599. return this.$message('请选择标签');
  600. }
  601. this.changeTagDialog.open = false;
  602. },
  603. //取消选择标签
  604. tagCancel(){
  605. this.changeTagDialog.open = false;
  606. },
  607. //删除一些选择的标签
  608. handleCloseTags(list){
  609. const ls = this.selectTags.findIndex(t => t.tagId === list.tagId);
  610. if (ls !== -1) {
  611. this.selectTags.splice(ls, 1);
  612. this.selectTags = [...this.selectTags];
  613. }
  614. if (this.selectTags!=null && this.selectTags.length>0){
  615. // 确保 this.form.tags 是数组
  616. if (!this.queryParams.tagIds) {
  617. this.queryParams.tagIds = []; // 如果未定义,初始化
  618. } else {
  619. this.queryParams.tagIds = []; // 清空已有数据
  620. }
  621. // 遍历并添加 tagId
  622. this.selectTags.forEach(tag => {
  623. if (tag.tagId) { // 确保 tagId 存在
  624. this.queryParams.tagIds.push(tag.tagId);
  625. }
  626. });
  627. this.queryParams.tagIds=this.queryParams.tagIds.join(",");
  628. }else {
  629. this.queryParams.tagIds=null;
  630. }
  631. },
  632. handleSearchTags(name){
  633. searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
  634. this.tagGroupList = response.rows;
  635. });
  636. },
  637. cancelSearchTags(){
  638. this.resetSearchQueryTag()
  639. this.getPageListTagGroup();
  640. },
  641. getPageListTagGroup(){
  642. this.queryTagParams.corpId=this.queryParams.corpId
  643. allListTagGroup(this.queryTagParams).then(response => {
  644. this.tagGroupList = response.rows;
  645. this.tagTotal = response.total;
  646. });
  647. },
  648. resetSearchQueryTag(){
  649. this.queryTagParams= {
  650. pageNum: 1,
  651. pageSize: 10,
  652. total:0,
  653. name:null,
  654. };
  655. },
  656. courseChange() {
  657. if (this.msgForm.courseId != null ) {
  658. const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
  659. for (let i = 0; i < this.setting.length; i++) {
  660. //响应式直接给链接的标题/封面上值
  661. if (selectedCourse && this.msgForm.courseId != null) {
  662. if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ){
  663. this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
  664. this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
  665. }
  666. if ( this.setting[i].contentType == 4 ){
  667. this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
  668. }
  669. }
  670. }
  671. }
  672. videoList(this.msgForm.courseId).then(response => {
  673. this.videoList=response.list;
  674. });
  675. },
  676. videoIdChange() {
  677. if (this.msgForm.videoId != null ) {
  678. // 查找选中的课节对应的 label
  679. const selectedVideo = this.videoList.find(course => parseInt(course.dictValue) === this.msgForm.videoId);
  680. for (let i = 0; i < this.setting.length; i++) {
  681. //响应式直接给链接的描述上值
  682. if (selectedVideo && this.msgForm.videoId != null) {
  683. if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ){
  684. this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
  685. }
  686. if (this.setting[i].contentType == 4){
  687. this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
  688. }
  689. }
  690. }
  691. }
  692. },
  693. handleAvatarSuccessFile(res, file, item) {
  694. if (res.code === 200) {
  695. // 使用 $set 确保响应式更新
  696. this.$set(item, 'fileUrl', res.url);
  697. } else {
  698. this.msgError(res.msg);
  699. }
  700. },
  701. beforeAvatarUploadFile(file){
  702. const isLt1M = file.size / 1024 / 1024 < 10;
  703. if (!isLt1M) {
  704. this.$message.error('上传大小不能超过 10MB!');
  705. }
  706. return isLt1M;
  707. },
  708. //下载文件
  709. downloadUrl(materialUrl) {
  710. // 直接返回文件 URL
  711. return materialUrl;
  712. },
  713. handleAvatarSuccessVideo(res, file, item) {
  714. if(res.code==200){
  715. // 使用 $set 确保响应式更新
  716. this.$set(item, 'videoUrl', res.url);
  717. }
  718. else{
  719. this.msgError(res.msg);
  720. }
  721. },
  722. beforeAvatarUploadVideo(file){
  723. const isLt30M = file.size / 1024 / 1024 < 10;
  724. const isMP4 = file.type === 'video/mp4';
  725. if (!isMP4) {
  726. this.$message.error('仅支持上传 MP4 格式的视频文件!');
  727. return false;
  728. }
  729. if (!isLt30M) {
  730. this.$message.error('上传大小不能超过 10MB!');
  731. return false;
  732. }
  733. return true;
  734. },
  735. handleInputVideoText(value,content){
  736. // 允许的字符:中文、英文(大小写)、数字和指定标点符号(,。!?)
  737. const regex = /^[\u4e00-\u9fa5,。!?,!?]+$/;
  738. // 删除不符合条件的字符
  739. const filteredValue = value.split('').filter(char => regex.test(char)).join('');
  740. this.$set(content, 'value', filteredValue);
  741. },
  742. delSetList(index){
  743. this.setting.splice(index,1)
  744. },
  745. addSetList(){
  746. const newSetting = {
  747. contentType:'1',
  748. value: '',
  749. };
  750. // 将新设置项添加到 content.setting 数组中
  751. this.setting.push(newSetting);
  752. },
  753. handleKeydown(event, index) {
  754. const item = this.setting[index];
  755. const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
  756. const cursorPosition = textarea.selectionStart;
  757. // 检查是否按下了 Backspace 或 Delete 键
  758. if (event.key === 'Backspace' || event.key === 'Delete') {
  759. const tags = ['#销售称呼#', '#客户称呼#']; // 需要检查的标签
  760. const value = item.value;
  761. // 遍历标签,检查是否需要删除
  762. for (const tag of tags) {
  763. let start, end;
  764. if (event.key === 'Backspace') {
  765. // 检查光标前是否是当前标签的一部分
  766. start = cursorPosition - tag.length;
  767. if (start >= 0 && value.slice(start, cursorPosition) === tag) {
  768. // 删除整个标签
  769. item.value = value.slice(0, start) + value.slice(cursorPosition);
  770. // 更新光标位置
  771. this.$nextTick(() => {
  772. textarea.setSelectionRange(start, start);
  773. });
  774. // 更新状态
  775. if (tag === '#销售称呼#') item.isSalesCallAdded = false;
  776. if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
  777. event.preventDefault(); // 阻止默认删除行为
  778. break; // 找到匹配的标签后退出循环
  779. }
  780. } else if (event.key === 'Delete') {
  781. // 检查光标后是否是当前标签的一部分
  782. end = cursorPosition + tag.length;
  783. if (end <= value.length && value.slice(cursorPosition, end) === tag) {
  784. // 删除整个标签
  785. item.value = value.slice(0, cursorPosition) + value.slice(end);
  786. // 更新状态
  787. if (tag === '#销售称呼#') item.isSalesCallAdded = false;
  788. if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
  789. event.preventDefault(); // 阻止默认删除行为
  790. break; // 找到匹配的标签后退出循环
  791. }
  792. }
  793. // 检查光标是否位于标签的中间
  794. for (let i = 0; i <= tag.length; i++) {
  795. const tagStart = cursorPosition - i;
  796. const tagEnd = tagStart + tag.length;
  797. if (
  798. tagStart >= 0 &&
  799. tagEnd <= value.length &&
  800. value.slice(tagStart, tagEnd) === tag
  801. ) {
  802. // 删除整个标签
  803. item.value = value.slice(0, tagStart) + value.slice(tagEnd);
  804. // 更新光标位置
  805. this.$nextTick(() => {
  806. textarea.setSelectionRange(tagStart, tagStart);
  807. });
  808. // 更新状态
  809. if (tag === '#销售称呼#') item.isSalesCallAdded = false;
  810. if (tag === '#客户称呼#') item.isSalesCallCustomerAdded = false;
  811. event.preventDefault(); // 阻止默认删除行为
  812. break; // 找到匹配的标签后退出循环
  813. }
  814. }
  815. }
  816. }
  817. },
  818. // 切换添加销售称呼按钮点击事件
  819. toggleSalesCall(index) {
  820. const item = this.setting[index];
  821. const salesCall = '#销售称呼#';
  822. const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
  823. // 获取当前光标位置
  824. const cursorPosition = textarea.selectionStart;
  825. if (item.isSalesCallAdded) {
  826. // 移除所有的 #销售称呼#
  827. item.value = item.value.replace(new RegExp(salesCall, 'g'), '');
  828. } else {
  829. // 添加 #销售称呼#
  830. item.value = item.value.slice(0, cursorPosition) + salesCall + item.value.slice(cursorPosition);
  831. }
  832. // 切换状态
  833. item.isSalesCallAdded = !item.isSalesCallAdded;
  834. // 保持光标位置
  835. this.$nextTick(() => {
  836. textarea.setSelectionRange(cursorPosition, cursorPosition);
  837. });
  838. },
  839. toggleSalesCallCustomer(index) {
  840. const item = this.setting[index];
  841. const salesCall = '#客户称呼#';
  842. const textarea = this.$refs[`textarea-${index}`][0].$refs.textarea;
  843. // 获取当前光标位置
  844. const cursorPosition = textarea.selectionStart;
  845. if (item.isSalesCallCustomerAdded) {
  846. // 移除所有的 #销售称呼#
  847. item.value = item.value.replace(new RegExp(salesCall, 'g'), '');
  848. } else {
  849. // 添加 #客户称呼#
  850. item.value = item.value.slice(0, cursorPosition) + salesCall + item.value.slice(cursorPosition);
  851. }
  852. // 切换状态
  853. item.isSalesCallCustomerAdded = !item.isSalesCallCustomerAdded;
  854. // 保持光标位置
  855. this.$nextTick(() => {
  856. textarea.setSelectionRange(cursorPosition, cursorPosition);
  857. });
  858. },
  859. handleContentTypeChange() {
  860. //如果是链接的才上
  861. if (this.msgForm.courseId != null ) {
  862. const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
  863. for (let i = 0; i < this.setting.length; i++) {
  864. //响应式直接给链接的标题/封面上值
  865. if (selectedCourse && this.msgForm.courseId != null) {
  866. if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9){
  867. this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
  868. this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
  869. }
  870. if (this.setting[i].contentType == 4){
  871. this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
  872. }
  873. }
  874. }
  875. }
  876. if (this.msgForm.videoId != null ) {
  877. // 查找选中的课节对应的 label
  878. const selectedVideo = this.videoList.find(course => parseInt(course.dictValue) === this.msgForm.videoId);
  879. for (let i = 0; i < this.setting.length; i++) {
  880. //响应式直接给链接的描述上值
  881. if (selectedVideo && this.msgForm.videoId != null) {
  882. if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9){
  883. this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
  884. }
  885. if (this.setting[i].contentType == 4){
  886. this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
  887. }
  888. }
  889. }
  890. }
  891. },
  892. /** 查询sopUserLogsInfo列表 */
  893. getList() {
  894. this.loading = true;
  895. listSopUserLogsInfo(this.queryParams).then(response => {
  896. this.sopUserLogsInfoList = response.rows;
  897. this.total = response.total;
  898. this.loading = false;
  899. });
  900. },
  901. // 取消按钮
  902. cancel() {
  903. this.updateOpen = false;
  904. this.reset();
  905. },
  906. // 表单重置
  907. reset() {
  908. this.form = {
  909. id: null,
  910. sopId: null,
  911. userLogsId: null,
  912. externalContactId: null,
  913. qwUserId: null,
  914. corpId: null,
  915. externalId: null,
  916. fsUserId: null,
  917. externalUserName: null,
  918. createTime: null,
  919. crtTime: null,
  920. updateTime: null
  921. };
  922. this.resetForm("form");
  923. },
  924. resetSendMsgSop() {
  925. this.msgForm = {
  926. videoId:null,
  927. courseId:null,
  928. courseType:null,
  929. setting:null,
  930. ids:null,
  931. };
  932. this.resetForm("msgForm");
  933. },
  934. /** 搜索按钮操作 */
  935. handleQuery() {
  936. if (this.selectTags!=null && this.selectTags.length>0){
  937. // 确保 this.form.tags 是数组
  938. if (!this.queryParams.tagIds) {
  939. this.queryParams.tagIds = []; // 如果未定义,初始化
  940. } else {
  941. this.queryParams.tagIds = []; // 清空已有数据
  942. }
  943. // 遍历并添加 tagId
  944. this.selectTags.forEach(tag => {
  945. if (tag.tagId) { // 确保 tagId 存在
  946. this.queryParams.tagIds.push(tag.tagId);
  947. }
  948. });
  949. this.queryParams.tagIds=this.queryParams.tagIds.join(",");
  950. }else {
  951. this.queryParams.tagIds=null;
  952. }
  953. this.getList();
  954. },
  955. /** 重置按钮操作 */
  956. resetQuery() {
  957. this.selectTags=[];
  958. this.resetForm("queryForm");
  959. this.handleQuery();
  960. },
  961. // 多选框选中数据
  962. handleSelectionChange(selection) {
  963. this.ids = selection.map(item => item.id)
  964. this.single = selection.length!==1
  965. this.multiple = !selection.length
  966. },
  967. /** 新增按钮操作 */
  968. handleAdd() {
  969. this.reset();
  970. this.open = true;
  971. this.title = "添加客户营期";
  972. },
  973. /**
  974. * 一键群发
  975. */
  976. handleSendMsg(){
  977. this.sendMsgOpen.open=true;
  978. this.sendMsgOpen.ids=this.ids;
  979. },
  980. /** 修改按钮操作 */
  981. handleUpdate() {
  982. this.updateOpen= true;
  983. },
  984. submitMsgForm(){
  985. this.$refs["msgForm"].validate(valid => {
  986. if (valid) {
  987. this.msgForm.setting=JSON.stringify(this.setting)
  988. this.msgForm.ids=this.ids;
  989. this.msgForm.sopId=this.queryParams.sopId;
  990. this.msgForm.userIdParam=this.queryParams.userIdParam;
  991. this.msgForm.startTime=this.queryParams.startTimeParam;
  992. this.msgForm.corpId=this.queryParams.corpIdParam;
  993. this.msgForm.filterMode=this.queryParams.filterMode;
  994. if (this.setting.length <= 0) {
  995. return this.$message.error("请添加规则")
  996. }
  997. if (this.msgForm.courseId===null || this.msgForm.courseId===''){
  998. return this.$message.error("课程不能为空")
  999. }
  1000. if (this.msgForm.videoId===null || this.msgForm.videoId===''){
  1001. return this.$message.error("课节不能为空")
  1002. }
  1003. if (this.msgForm.courseType===null || this.msgForm.courseType===''){
  1004. return this.$message.error("消息类型不能为空")
  1005. }
  1006. for (let i = 0; i < this.setting.length; i++) {
  1007. if (this.setting[i].contentType == 1 && (this.setting[i].value == null || this.setting[i].value == "")) {
  1008. return this.$message.error("内容不能为空")
  1009. }
  1010. if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
  1011. return this.$message.error("图片不能为空")
  1012. }
  1013. if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ) && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
  1014. return this.$message.error("链接标题不能为空")
  1015. }
  1016. if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ) && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
  1017. return this.$message.error("链接描述不能为空")
  1018. }
  1019. if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 ) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
  1020. return this.$message.error("链接图片不能为空")
  1021. }
  1022. if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 )&& this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
  1023. return this.$message.error("链接地址不能为空")
  1024. }
  1025. if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramTitle == null || this.setting[i].miniprogramTitle == "")) {
  1026. return this.$message.error("小程序消息标题不能为空")
  1027. }
  1028. if (this.setting[i].contentType == 4 && (this.setting[i].miniprogramPicUrl == null || this.setting[i].miniprogramPicUrl == "")) {
  1029. return this.$message.error("小程序封面地址不能为空")
  1030. }
  1031. if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
  1032. return this.$message.error("文件不能为空")
  1033. }
  1034. if (this.setting[i].contentType == 6 && (this.setting[i].videoUrl == null || this.setting[i].videoUrl == "")) {
  1035. return this.$message.error("视频不能为空")
  1036. }
  1037. if (this.setting[i].contentType == 7 && (this.setting[i].value == null || this.setting[i].value == "")) {
  1038. return this.$message.error("语音不能为空")
  1039. }
  1040. }
  1041. this.sendMsgOpen.open = false;
  1042. const loading = this.$loading({
  1043. lock: true,
  1044. text: '正在执行中请稍后~~请不要刷新页面!!',
  1045. spinner: 'el-icon-loading',
  1046. background: 'rgba(0, 0, 0, 0.7)'
  1047. });
  1048. sendMsgSop(this.msgForm).then(response => {
  1049. this.msgSuccess("一键群发成功");
  1050. loading.close();
  1051. this.setting=[];
  1052. this.msgForm = {
  1053. videoId:null,
  1054. courseId:null,
  1055. courseType:null,
  1056. setting:null,
  1057. }
  1058. this.getList();
  1059. }).finally(()=>{
  1060. loading.close();
  1061. });
  1062. }
  1063. });
  1064. },
  1065. cancelMsgForm(){
  1066. this.sendMsgOpen.open = false;
  1067. this.resetSendMsgSop();
  1068. },
  1069. /** 提交按钮 */
  1070. submitForm() {
  1071. this.$refs["updateLogsInfoFrom"].validate(valid => {
  1072. if (valid) {
  1073. this.updateLogsInfoFrom.ids=this.ids;
  1074. this.updateLogsInfoFrom.sopId= this.queryParams.sopId
  1075. this.updateLogsInfoFrom.qwUserId=this.queryParams.qwUserId
  1076. this.updateLogsInfoFrom.corpId= this.queryParams.corpId
  1077. let loadingRock = this.$loading({
  1078. lock: true,
  1079. text: '正在执行中请稍后~~请不要刷新页面!!',
  1080. spinner: 'el-icon-loading',
  1081. background: 'rgba(0, 0, 0, 0.7)'
  1082. });
  1083. batchUpdateSopUserLogsInfoToTime(this.updateLogsInfoFrom).then(response => {
  1084. this.msgSuccess("修改成功");
  1085. this.open = false;
  1086. this.updateOpen=false;
  1087. this.getList();
  1088. this.$emit('flashNotify')
  1089. loadingRock.close();
  1090. }).finally(res=>{
  1091. loadingRock.close();
  1092. })
  1093. }
  1094. });
  1095. },
  1096. /** 删除按钮操作 */
  1097. handleDelete(row) {
  1098. const ids = row.id || this.ids;
  1099. this.$confirm('是否确认删除sopUserLogsInfo编号为"' + ids + '"的数据项?', "警告", {
  1100. confirmButtonText: "确定",
  1101. cancelButtonText: "取消",
  1102. type: "warning"
  1103. }).then(function() {
  1104. return delSopUserLogsInfo(ids);
  1105. }).then(() => {
  1106. this.getList();
  1107. this.msgSuccess("删除成功");
  1108. }).catch(() => {});
  1109. },
  1110. /** 导出按钮操作 */
  1111. handleExport() {
  1112. const queryParams = this.queryParams;
  1113. this.$confirm('是否确认导出所有营期数据项?', "警告", {
  1114. confirmButtonText: "确定",
  1115. cancelButtonText: "取消",
  1116. type: "warning"
  1117. }).then(() => {
  1118. this.exportLoading = true;
  1119. return exportSopUserLogsInfo(queryParams);
  1120. }).then(response => {
  1121. this.download(response.msg);
  1122. this.exportLoading = false;
  1123. }).catch(() => {});
  1124. }
  1125. }
  1126. };
  1127. </script>
  1128. <style scoped>
  1129. /* CSS 样式 */
  1130. .tag-container {
  1131. display: flex;
  1132. flex-wrap: wrap; /* 超出宽度时自动换行 */
  1133. gap: 8px; /* 设置标签之间的间距 */
  1134. }
  1135. .name-background {
  1136. display: inline-block;
  1137. background-color: #abece6; /* 背景颜色 */
  1138. padding: 4px 8px; /* 调整内边距,让背景包裹文字 */
  1139. border-radius: 4px; /* 可选:设置圆角 */
  1140. }
  1141. .tag-box {
  1142. padding: 8px 12px;
  1143. border: 1px solid #989797;
  1144. border-radius: 4px;
  1145. cursor: pointer;
  1146. display: inline-block;
  1147. }
  1148. .tag-selected {
  1149. background-color: #00bc98;
  1150. color: #fff;
  1151. border-color: #00bc98;
  1152. }
  1153. .el-tag + .el-tag {
  1154. margin-left: 10px;
  1155. }
  1156. .button-new-tag {
  1157. margin-left: 10px;
  1158. height: 32px;
  1159. line-height: 30px;
  1160. padding-top: 0;
  1161. padding-bottom: 0;
  1162. }
  1163. .input-new-tag {
  1164. width: 90px;
  1165. margin-left: 10px;
  1166. vertical-align: bottom;
  1167. }
  1168. </style>