specialResearch.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. <script>
  2. import { defineComponent } from "vue";
  3. export default defineComponent({
  4. beforeRouteEnter(to, from, next) {
  5. if (from.path !== "/addResearch" && from.path !== "/determineTravel" && from.path !== "/editResearch") {
  6. sessionStorage.removeItem("specialResearchListBack");
  7. }
  8. next();
  9. },
  10. });
  11. </script>
  12. <script setup>
  13. import { ref, watch, onMounted, reactive, computed, toRefs } from "vue";
  14. import { raiInterface, raiSpecial } from "@/api/api.js";
  15. import mPage from "@/components/mPage.vue";
  16. import { inAdvanceOptions, tableColums, TabsTop, ConfirmOptions } from "../components/special/optionsTabs";
  17. import ParticalDialog from "../components/particalDialog.vue";
  18. import ApplyDialog from "../components/apply/applyDialog.vue";
  19. import ParticularsAll from "./specialResearch/particularsAll.vue";
  20. import SpecialResearchDlg from "../components/special/specialResearchDlg.vue";
  21. import TemplateMessage from "../components/apply/templateMessage.vue";
  22. import { ElMessageBox, ElMessage } from "element-plus";
  23. import moment from "moment";
  24. import { Search } from "@element-plus/icons-vue";
  25. import { onBeforeRouteLeave, useRouter, useRoute } from "vue-router";
  26. const $route = useRoute();
  27. const $router = useRouter();
  28. const pageState = reactive({
  29. status: "",
  30. industryValue: "",
  31. chartPermissionList: [],
  32. themeVal: "",
  33. dataList: [],
  34. page_no: 1,
  35. total: 0,
  36. dialogVisibleActivity: false,
  37. dialogTitle: "",
  38. activityDetail: {},
  39. previewList: [],
  40. interestData: [], //感兴趣人数
  41. exportInterest: "",
  42. tableColums: [],
  43. tabsActive: 1,
  44. offlineId: 0, //提交的ID
  45. dialogVisiblepartica: false, //到会详情的隐现
  46. particlaDlg: {
  47. isSpecial: true,
  48. title: "到会详情",
  49. }, //提交的标题
  50. submitDialog: false, //提交到会情况的隐现
  51. addDialogVisible: false,
  52. signUpAdd: "专项",
  53. addDialogType: "新增报名",
  54. particularsDialogVisible: false,
  55. dialogVisibleList: {},
  56. specialDetailId: 0,
  57. selectList: [],
  58. messageDialogVisible: false, // 发送模版消息
  59. selectionArr: {},
  60. });
  61. const options = computed(() => {
  62. return pageState.tabsActive == 1 ? inAdvanceOptions : ConfirmOptions;
  63. });
  64. const tabsTop = computed(() => {
  65. return TabsTop;
  66. });
  67. //点击了头部切换
  68. function tabsHandle(item) {
  69. pageState.tabsActive = item.id;
  70. pageState.tableColums = tableColums(pageState.tabsActive);
  71. pageState.status = "";
  72. pageState.page_no = 1;
  73. getsDataList();
  74. }
  75. //change 变化
  76. function changeHandel() {
  77. pageState.page_no = 1;
  78. getsDataList();
  79. }
  80. //分页
  81. function handleCurrentChange(page) {
  82. pageState.page_no = page;
  83. getsDataList();
  84. }
  85. //获取表格
  86. async function getsDataList() {
  87. const res = await raiSpecial.getSpecialList({
  88. PageSize: 10,
  89. CurrentIndex: pageState.page_no,
  90. PublishStatus: pageState.status ? Number(pageState.status) : 2,
  91. ChartPermissionId: pageState.industryValue,
  92. IsTrip: pageState.tabsActive == 2,
  93. KeyWord: pageState.themeVal,
  94. });
  95. if (res.Ret === 200) {
  96. pageState.dataList = res.Data.List;
  97. pageState.total = res.Data.Paging.Totals;
  98. }
  99. }
  100. //获取行业
  101. function chartPermission() {
  102. raiInterface.getActivitySpecial().then((res) => {
  103. if (res.Ret === 200) {
  104. pageState.chartPermissionList = res.Data.List;
  105. }
  106. });
  107. }
  108. //获取调研主题详情
  109. async function themeDetails(id) {
  110. pageState.specialDetailId = id;
  111. pageState.dialogVisibleActivity = true;
  112. pageState.dialogTitle = "活动详情";
  113. return;
  114. const res = await raiSpecial.specialDetail({ ActivityId: id });
  115. if (res.Ret === 200) {
  116. pageState.previewList = [];
  117. pageState.activityDetail = res.Data;
  118. pageState.previewList.push(pageState.tabsActive == 1 ? pageState.activityDetail.TripImgLink : pageState.activityDetail.TripImgLinkFix);
  119. }
  120. }
  121. //感兴趣人数
  122. async function interestDetails(id) {
  123. pageState.specialDetailId = id;
  124. pageState.dialogTitle = "感兴趣人数";
  125. pageState.dialogVisibleActivity = true;
  126. return;
  127. const res = await raiSpecial.specialInterested({ ActivityId: id });
  128. if (res.Ret === 200) {
  129. pageState.exportInterest = `${import.meta.env.VITE_APP_API_ROOT}/cygx/special/export?${localStorage.getItem("auth") || ""}&ActivityId=${id}`;
  130. nextTick(() => {
  131. pageState.interestData = res.Data.List;
  132. });
  133. }
  134. }
  135. //发布、取消发布 、删除、下线、重新发布、取消发布
  136. function applyHandleAllOperate(id, value) {
  137. ElMessageBox.confirm(`确定${value}该活动吗?`, "提示", {
  138. confirmButtonText: "确定",
  139. cancelButtonText: "取消",
  140. type: "warning",
  141. })
  142. .then(async () => {
  143. const res =
  144. value == "删除"
  145. ? await raiSpecial.specialDelete({
  146. ActivityId: id,
  147. })
  148. : value == "发布"
  149. ? await raiSpecial.specialPublishAndCancel({
  150. ActivityId: id,
  151. })
  152. : value == "下线"
  153. ? await await raiSpecial.postSpecialOffline({
  154. ActivityId: id,
  155. })
  156. : value == "取消发布"
  157. ? await raiSpecial.specialPublishAndCancel({
  158. ActivityId: id,
  159. })
  160. : value == "重新发布" && pageState.tabsActive == 1
  161. ? await await await raiSpecial.postSpecialOffline({
  162. ActivityId: id,
  163. })
  164. : await await raiSpecial.specialPublishAndCancel({
  165. ActivityId: id,
  166. });
  167. if (res.Ret !== 200) return;
  168. ElMessage.success(`${value}成功!`);
  169. if (value == "删除") {
  170. let page_num = Math.ceil((pageState.total - 1) / 10);
  171. if (pageState.page_no > page_num) {
  172. pageState.page_no = page_num;
  173. }
  174. }
  175. getsDataList();
  176. })
  177. .catch(() => {
  178. ElMessage({
  179. type: "info",
  180. message: `已取消${value}`,
  181. });
  182. });
  183. }
  184. //点击了编辑
  185. function editBtn(id, show, type = "") {
  186. type == ""
  187. ? $router.push({
  188. path: "/editResearch",
  189. query: { id, isShow: show },
  190. })
  191. : $router.push({
  192. path: "/determineTravel",
  193. query: { id },
  194. });
  195. }
  196. //提交到会情况
  197. function particularsSubmit(id) {
  198. pageState.offlineId = id;
  199. pageState.submitDialog = true;
  200. }
  201. //到会详情
  202. function particulars(id) {
  203. pageState.offlineId = id;
  204. pageState.dialogVisiblepartica = true;
  205. }
  206. function handleCloseSubject() {
  207. pageState.dialogTitle = "";
  208. pageState.exportInterest = "";
  209. pageState.activityDetail = {};
  210. pageState.dialogVisibleActivity = false;
  211. }
  212. //感兴趣人数总览
  213. function interestHandler() {
  214. let routeUrl = $router.resolve("/interestAllPreview");
  215. window.open(routeUrl.href, "_blank");
  216. }
  217. function applyNum(item) {
  218. pageState.particularsDialogVisible = true;
  219. pageState.dialogVisibleList = item;
  220. }
  221. /* 表格行的样式 */
  222. function handleRowStyle(key) {
  223. const style = {
  224. ResearchTheme: "color: #409eff; cursor: pointer",
  225. InterestedNum: "color: #409eff; cursor: pointer",
  226. SignupPeopleNum: "color: #409eff; cursor: pointer",
  227. };
  228. return style[key] ? style[key] : "";
  229. }
  230. /* 表格行的点击事件 */
  231. function handleRowClick(row, key) {
  232. if (key === "ResearchTheme") {
  233. themeDetails(row.ActivityId);
  234. } else if (key === "InterestedNum") {
  235. interestDetails(row.ActivityId);
  236. } else if (key === "SignupPeopleNum") {
  237. applyNum(row);
  238. }
  239. }
  240. /* 表格行的数据处理 */
  241. function handleRowContent(row, key) {
  242. if (key == "SpecialType") {
  243. return row[key] == 1 ? "线上" : `线下(${row["City"]})`;
  244. } else if (key == "PublishStatus") {
  245. return row[key] == 1
  246. ? "已发布"
  247. : row[key] == 0 && pageState.tabsActive == 1
  248. ? "未发布"
  249. : row[key] == 0 && pageState.tabsActive == 2
  250. ? "已取消"
  251. : row[key] == 3
  252. ? "已下线"
  253. : row[key] == 4
  254. ? "已确定行程"
  255. : "";
  256. } else if (key == "InterestedNum") {
  257. return row[key] ? row[key] : "";
  258. } else {
  259. return row[key];
  260. }
  261. }
  262. // 新增活动报名
  263. function addapply() {
  264. if (!this.selectList) returnElMessage.error("请先选择活动");
  265. pageState.addDialogVisible = true;
  266. }
  267. // 新增活动报名的表格选择
  268. function selectChange(selection) {
  269. pageState.selectionArr = selection;
  270. let arr = [];
  271. selection.forEach((item) => {
  272. arr.push(item.ActivityId);
  273. });
  274. pageState.selectList = arr.join(",");
  275. }
  276. // 判断活动时间对比当前时间
  277. function isStart(val) {
  278. return moment().isBefore(val);
  279. }
  280. // 主题名称的输入框
  281. function themeInput() {
  282. pageState.page_no = 1;
  283. pageState.status = "";
  284. pageState.industryValue = "";
  285. getsDataList();
  286. }
  287. // 发送模版消息
  288. function sendMessage() {
  289. if (pageState.selectList && pageState.selectList.split(",").length === 1) {
  290. pageState.messageDialogVisible = true;
  291. } else {
  292. ElMessage.error("请选择一个活动");
  293. }
  294. }
  295. onMounted(() => {
  296. if (sessionStorage.getItem("specialResearchListBack")) {
  297. let { tabsActive, page, status, industryValue, themeVal } = JSON.parse(sessionStorage.getItem("specialResearchListBack"));
  298. pageState.themeVal = themeVal;
  299. pageState.page_no = page;
  300. pageState.tabsActive = tabsActive;
  301. pageState.status = status;
  302. pageState.industryValue = industryValue;
  303. }
  304. chartPermission();
  305. getsDataList();
  306. pageState.tableColums = tableColums(pageState.tabsActive);
  307. });
  308. onBeforeRouteLeave((to, from, next) => {
  309. let obj = {
  310. page: pageState.page_no,
  311. tabsActive: pageState.tabsActive,
  312. status: pageState.status,
  313. industryValue: pageState.industryValue,
  314. themeVal: pageState.themeVal,
  315. };
  316. sessionStorage.setItem("specialResearchListBack", JSON.stringify(obj));
  317. next();
  318. });
  319. const {
  320. status,
  321. industryValue,
  322. chartPermissionList,
  323. themeVal,
  324. dataList,
  325. page_no,
  326. total,
  327. dialogVisibleActivity,
  328. dialogTitle,
  329. activityDetail,
  330. previewList,
  331. interestData, //感兴趣人数
  332. exportInterest,
  333. tableColums,
  334. tabsActive,
  335. offlineId, //提交的ID
  336. dialogVisiblepartica, //到会详情的隐现
  337. particlaDlg, //提交的标题
  338. submitDialog, //提交到会情况的隐现
  339. addDialogVisible,
  340. signUpAdd,
  341. addDialogType,
  342. particularsDialogVisible,
  343. dialogVisibleList,
  344. specialDetailId,
  345. selectList,
  346. messageDialogVisible, // 发送模版消息
  347. selectionArr,
  348. } = toRefs(pageState);
  349. </script>
  350. <template>
  351. <div class="container special-research">
  352. <div class="top-wrap">
  353. <div class="tabs-content">
  354. <span @click="tabsHandle(item)" :class="['item', tabsActive == item.id && 'active-item']" v-for="item in tabsTop" :key="item.id">{{ item.name }}</span>
  355. </div>
  356. </div>
  357. <div class="top-wrap">
  358. <div>
  359. <el-button v-if="tabsActive == 2" type="primary" style="margin-right: 20px" @click="addapply">新增报名</el-button>
  360. <el-button v-if="tabsActive == 2" type="primary" @click="sendMessage" style="margin-right: 20px">发送模板消息</el-button>
  361. <el-select placeholder="请选择行业" clearable v-model="industryValue" @change="changeHandel" style="margin: 0 20px 20px 0">
  362. <el-option v-for="item in chartPermissionList" :label="item.PermissionName" :key="item.ChartPermissionId" :value="item.ChartPermissionId"></el-option>
  363. </el-select>
  364. <el-select placeholder="发布状态" clearable v-model="status" @change="changeHandel" style="margin: 0 30px 20px 0">
  365. <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id"></el-option>
  366. </el-select>
  367. <template v-if="tabsActive == 1">
  368. <el-button style="margin-bottom: 20px" type="primary" @click="$router.push('/addResearch')">添加活动</el-button>
  369. <el-button style="margin-bottom: 20px" type="primary" @click="interestHandler">客户兴趣总览</el-button>
  370. </template>
  371. </div>
  372. <div style="width: 520px">
  373. <el-input v-model="themeVal" @input="themeInput" placeholder="请输入主题名称" clearable :prefix-icon="Search"> </el-input>
  374. </div>
  375. </div>
  376. <el-card>
  377. <el-table @selection-change="selectChange" :data="dataList" style="width: 100%; margin-top: 20px" border>
  378. <el-table-column v-if="tabsActive == 2" align="center" type="selection" width="55"> </el-table-column>
  379. <el-table-column v-for="item in tableColums" :key="item.label" :label="item.label" :width="item.widthsty" :min-width="item.minwidthsty" align="center">
  380. <template #default="{ row }">
  381. <span @click="handleRowClick(row, item.key)" :style="handleRowStyle(item.key)">{{ handleRowContent(row, item.key) }}</span>
  382. </template>
  383. </el-table-column>
  384. <el-table-column width="230" prop="" align="center" label="操作">
  385. <template #default="{ row }">
  386. <div v-if="tabsActive == 1">
  387. <template v-if="row.PublishStatus !== 4">
  388. <span class="editsty" v-if="row.PublishStatus == 1" @click="applyHandleAllOperate(row.ActivityId, '下线')">下线 &nbsp;&nbsp;</span>
  389. <span class="editsty" v-if="row.PublishStatus == 3" @click="applyHandleAllOperate(row.ActivityId, '重新发布')">重新发布 &nbsp;&nbsp;</span>
  390. <span v-if="row.PublishStatus == 0" class="editsty" @click="applyHandleAllOperate(row.ActivityId, '发布')">发布 &nbsp;&nbsp;</span>
  391. <span class="editsty" @click="editBtn(row.ActivityId, row.PublishStatus, '')">编辑 &nbsp;&nbsp;</span>
  392. <span class="editsty" v-if="row.PublishStatus == 1" @click="editBtn(row.ActivityId, row.PublishStatus, '行程')">确定行程</span>
  393. <span class="deletesty" v-if="row.PublishStatus == 0" @click="applyHandleAllOperate(row.ActivityId, '删除')">删除</span>
  394. </template>
  395. </div>
  396. <div v-else>
  397. <span class="editsty" v-if="row.PublishStatus == 1 && isStart(row.ActivityTime)" @click="applyHandleAllOperate(row.ActivityId, '取消发布')">取消发布 &nbsp;&nbsp;</span>
  398. <span class="editsty" v-if="row.PublishStatus !== 1" @click="applyHandleAllOperate(row.ActivityId, '重新发布')">重新发布 &nbsp;&nbsp;</span>
  399. <span class="editsty" @click="editBtn(row.ActivityId, row.PublishStatus, '行程')">编辑 &nbsp;&nbsp;</span>
  400. <span class="editsty" v-if="row.IsShowUpdateMeeting" @click="particularsSubmit(row.ActivityId)"> 修改到会情况 </span>
  401. <span class="editsty" v-if="row.IsShowSubmitMeeting" @click="particularsSubmit(row.ActivityId)"> 提交到会情况 </span>
  402. <span class="editsty" v-if="row.IsShowAttendanceDetails" @click="particulars(row.ActivityId)">&nbsp;&nbsp;到会详情</span>
  403. </div>
  404. </template>
  405. </el-table-column>
  406. </el-table>
  407. <!-- 分页 -->
  408. <el-col :span="24" class="toolbar">
  409. <m-page :total="total" :page_no="page_no" :pageSize="10" @handleCurrentChange="handleCurrentChange" />
  410. </el-col>
  411. </el-card>
  412. <special-research-dlg :specialDetailId="specialDetailId" v-model:dialogVisibleActivity="dialogVisibleActivity" :dialogTitle="dialogTitle" :tabsActive="tabsActive" />
  413. <partical-dialog @getsDataList="getsDataList" @particulars="particulars" :offlineId="offlineId" v-model:dialogVisiblepartica="dialogVisiblepartica" :particlaDlg="particlaDlg" v-model:submitDialog="submitDialog" />
  414. <apply-dialog v-model:addDialogVisible="addDialogVisible" :selectList="selectList" :signUpAdd="signUpAdd" :addDialogType="addDialogType" @getsDataList="getsDataList" />
  415. <particulars-all v-model:particularsDialogVisible="particularsDialogVisible" :dialogVisibleList="dialogVisibleList" @getsDataList="getsDataList"/>
  416. <template-message v-model:messageDialog="messageDialogVisible" :selectionArr="selectionArr" typeMessage="确定行程" />
  417. </div>
  418. </template>
  419. <style scoped lang="scss">
  420. .special-research {
  421. .top-wrap {
  422. margin-bottom: 28px;
  423. padding: 20px 30px 0;
  424. background: #fff;
  425. border: 1px solid #ececec;
  426. border-radius: 4px;
  427. box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
  428. display: flex;
  429. justify-content: space-between;
  430. }
  431. .tabs-content {
  432. display: flex;
  433. padding-bottom: 20px;
  434. .item {
  435. display: flex;
  436. align-items: center;
  437. justify-content: center;
  438. padding: 0 18px;
  439. height: 40px;
  440. background: #ecf5ff;
  441. border-radius: 4px 4px 4px 4px;
  442. border: 1px solid #b3d8ff;
  443. margin-right: 20px;
  444. color: #3385ff;
  445. font-size: 16px;
  446. cursor: pointer;
  447. }
  448. .active-item {
  449. height: 40px;
  450. background: #409eff;
  451. color: #fff;
  452. }
  453. }
  454. .rai-detail-wrap {
  455. .activity-top {
  456. width: 100%;
  457. height: 55px;
  458. background: #f4f4f4;
  459. border-radius: 4px 4px 4px 4px;
  460. opacity: 1;
  461. line-height: 55px;
  462. padding-left: 23px;
  463. margin-bottom: 30px;
  464. }
  465. p {
  466. margin-bottom: 20px;
  467. padding-left: 10px;
  468. }
  469. .arrange {
  470. margin: 50px auto 20px;
  471. cursor: pointer;
  472. text-align: center;
  473. color: #3385ff;
  474. }
  475. .text-box {
  476. display: flex;
  477. padding-left: 10px;
  478. span {
  479. display: block;
  480. margin-bottom: 10px;
  481. }
  482. }
  483. }
  484. .dialog-footer {
  485. text-align: center;
  486. margin-bottom: 20px;
  487. }
  488. }
  489. </style>