activityList.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. <template>
  2. <div class="table-box button-table">
  3. <ProTable
  4. ref="proTable"
  5. :columns="columns"
  6. :request-api="getTableList"
  7. :init-param="initParam"
  8. :data-callback="dataCallback"
  9. :refresh-reset-page="true"
  10. >
  11. <template #tableHeader="scope">
  12. <div class="action-buttons">
  13. <el-button :icon="Plus" class="button" type="primary" @click="newActivity" v-if="type"> 新建活动 </el-button>
  14. </div>
  15. </template>
  16. <!-- 表格操作 -->
  17. <template #operation="scope">
  18. <!-- 上架按钮 -->
  19. <el-button
  20. v-if="canShowButton(scope.row.status, OPERATION_PERMISSIONS.上架)"
  21. link
  22. type="primary"
  23. @click="changeStatus(scope.row, 5)"
  24. >
  25. 上架
  26. </el-button>
  27. <!-- 下架按钮 -->
  28. <el-button
  29. v-if="canShowButton(scope.row.status, OPERATION_PERMISSIONS.下架)"
  30. link
  31. type="primary"
  32. @click="changeStatus(scope.row, 6)"
  33. >
  34. 下架
  35. </el-button>
  36. <!-- 编辑按钮 -->
  37. <el-button
  38. v-if="canShowButton(scope.row.status, OPERATION_PERMISSIONS.编辑)"
  39. link
  40. type="primary"
  41. @click="editRow(scope.row)"
  42. >
  43. 编辑
  44. </el-button>
  45. <!-- 查看详情按钮 -->
  46. <el-button
  47. v-if="canShowButton(scope.row.status, OPERATION_PERMISSIONS.查看详情)"
  48. link
  49. type="primary"
  50. @click="toDetail(scope.row)"
  51. >
  52. 查看详情
  53. </el-button>
  54. <!-- 上传活动结果按钮 -->
  55. <el-button
  56. v-if="canShowButton(scope.row.status, OPERATION_PERMISSIONS.上传活动结果) && !hasUploadedResult(scope.row)"
  57. link
  58. type="primary"
  59. @click="openUploadResultDrawer(scope.row)"
  60. >
  61. 上传活动结果
  62. </el-button>
  63. <!-- 删除按钮 -->
  64. <el-button
  65. v-if="canShowButton(scope.row.status, OPERATION_PERMISSIONS.删除)"
  66. link
  67. type="primary"
  68. @click="deleteRow(scope.row)"
  69. >
  70. 删除
  71. </el-button>
  72. <!-- 查看拒绝原因按钮 -->
  73. <el-button
  74. v-if="canShowButton(scope.row.status, OPERATION_PERMISSIONS.查看拒绝原因)"
  75. link
  76. type="primary"
  77. @click="viewRejectReason(scope.row)"
  78. >
  79. 查看拒绝原因
  80. </el-button>
  81. </template>
  82. </ProTable>
  83. <!-- 查看拒绝原因弹窗 -->
  84. <el-dialog v-model="rejectReasonDialogVisible" title="查看拒绝原因" width="600px">
  85. <div class="reject-reason-content">
  86. <div class="reject-reason-item">
  87. <div class="reject-reason-label">活动名称:</div>
  88. <div class="reject-reason-value">
  89. {{ rejectReasonData.name || "--" }}
  90. </div>
  91. </div>
  92. <div class="reject-reason-item">
  93. <div class="reject-reason-label">拒绝原因:</div>
  94. <div class="reject-reason-value reject-reason-text">
  95. {{ rejectReasonData.approvalComments || "暂无拒绝原因" }}
  96. </div>
  97. </div>
  98. </div>
  99. <template #footer>
  100. <div class="dialog-footer">
  101. <el-button type="primary" @click="closeRejectReasonDialog"> 确定 </el-button>
  102. </div>
  103. </template>
  104. </el-dialog>
  105. <!-- 上传活动结果抽屉 -->
  106. <el-drawer v-model="uploadResultDrawerVisible" title="活动结果" :size="500" direction="rtl">
  107. <div class="upload-result-content">
  108. <!-- 活动成果类型选择 -->
  109. <div class="result-type-section">
  110. <div class="result-type-label">活动成果</div>
  111. <el-radio-group v-model="uploadResultForm.resultType">
  112. <el-radio :label="0"> 文字 </el-radio>
  113. <el-radio :label="1"> 图片 </el-radio>
  114. </el-radio-group>
  115. </div>
  116. <!-- 文字输入 -->
  117. <div v-if="uploadResultForm.resultType === 0" class="result-content-section">
  118. <div class="result-content-label">文字</div>
  119. <el-input
  120. v-model="uploadResultForm.resultText"
  121. type="textarea"
  122. :rows="8"
  123. placeholder="请输入"
  124. maxlength="1000"
  125. show-word-limit
  126. />
  127. </div>
  128. <!-- 图片上传 -->
  129. <div v-if="uploadResultForm.resultType === 1" class="result-content-section">
  130. <div class="result-content-label">图片</div>
  131. <div class="upload-area-wrapper" :class="{ 'has-file': resultImageFileList.length >= 1 }">
  132. <el-upload
  133. v-model:file-list="resultImageFileList"
  134. :accept="'.jpg,.jpeg,.png'"
  135. :auto-upload="false"
  136. :limit="1"
  137. :on-change="handleResultImageChange"
  138. :on-exceed="handleResultImageExceed"
  139. :on-preview="handleResultImagePreview"
  140. :on-remove="handleResultImageRemove"
  141. :before-remove="handleResultImageBeforeRemove"
  142. list-type="picture-card"
  143. >
  144. <el-icon>
  145. <Plus />
  146. </el-icon>
  147. </el-upload>
  148. </div>
  149. </div>
  150. </div>
  151. <template #footer>
  152. <div class="drawer-footer">
  153. <el-button @click="closeUploadResultDrawer"> 取消 </el-button>
  154. <el-button type="primary" @click="submitUploadResult" :loading="uploadResultSubmitting"> 确定 </el-button>
  155. </div>
  156. </template>
  157. </el-drawer>
  158. <!-- 图片预览 -->
  159. <el-image-viewer
  160. v-if="resultImageViewerVisible"
  161. :url-list="resultImageViewerUrlList"
  162. :initial-index="resultImageViewerInitialIndex"
  163. @close="resultImageViewerVisible = false"
  164. />
  165. </div>
  166. </template>
  167. <script setup lang="tsx" name="activityList">
  168. import { reactive, ref, onMounted, computed, nextTick } from "vue";
  169. import { useRouter } from "vue-router";
  170. import { ElMessage, ElMessageBox, ElLoading } from "element-plus";
  171. import { Plus } from "@element-plus/icons-vue";
  172. import type { UploadFile, UploadFiles, UploadProps } from "element-plus";
  173. import ProTable from "@/components/ProTable/index.vue";
  174. import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
  175. import { getActivityList, deleteActivity, updateActivityStatus, uploadActivityResult } from "@/api/modules/operationManagement";
  176. import { uploadContractImage } from "@/api/modules/licenseManagement";
  177. import { localGet, usePermission } from "@/utils";
  178. const router = useRouter();
  179. const proTable = ref<ProTableInstance>();
  180. const type = ref(false);
  181. // 查看拒绝原因弹窗相关
  182. const rejectReasonDialogVisible = ref(false);
  183. const rejectReasonData = ref<any>({
  184. name: "",
  185. approvalComments: ""
  186. });
  187. // 上传活动结果抽屉相关
  188. const uploadResultDrawerVisible = ref(false);
  189. const uploadResultSubmitting = ref(false);
  190. const currentActivityId = ref<number>(0);
  191. const uploadResultForm = ref({
  192. resultType: 0, // 0-文字,1-图片
  193. resultText: "",
  194. resultMediaUrl: ""
  195. });
  196. const resultImageFileList = ref<UploadFile[]>([]);
  197. const resultImageViewerVisible = ref(false);
  198. const resultImageViewerUrlList = ref<string[]>([]);
  199. const resultImageViewerInitialIndex = ref(0);
  200. // 活动状态枚举
  201. const ACTIVITY_STATUS = {
  202. 待审核: 1,
  203. 未开始: 2,
  204. 审核驳回: 3,
  205. 进行中: 5,
  206. 已下架: 6,
  207. 已结束: 7,
  208. 审核通过: 8
  209. } as const;
  210. // 活动状态选项(用于搜索)
  211. const statusEnum = [
  212. { label: "待审核", value: "1" },
  213. { label: "未开始", value: "2" },
  214. { label: "审核驳回", value: "3" },
  215. { label: "进行中", value: "5" },
  216. { label: "已下架", value: "6" },
  217. { label: "已结束", value: "7" },
  218. { label: "审核通过", value: "8" }
  219. ];
  220. // 活动类型选项(用于搜索)
  221. const activityTypeEnum = [
  222. { label: "评论有礼", value: "COMMENT" },
  223. { label: "营销活动", value: "MARKETING" }
  224. ];
  225. // 操作按钮权限配置(根据状态-操作映射表)
  226. const OPERATION_PERMISSIONS = {
  227. 查看详情: [
  228. ACTIVITY_STATUS.待审核,
  229. ACTIVITY_STATUS.未开始,
  230. ACTIVITY_STATUS.进行中,
  231. ACTIVITY_STATUS.已下架,
  232. ACTIVITY_STATUS.已结束,
  233. ACTIVITY_STATUS.审核驳回
  234. ],
  235. 上架: [ACTIVITY_STATUS.已下架],
  236. 下架: [ACTIVITY_STATUS.进行中],
  237. 编辑: [ACTIVITY_STATUS.未开始, ACTIVITY_STATUS.审核驳回, ACTIVITY_STATUS.已下架, ACTIVITY_STATUS.已结束],
  238. 删除: [ACTIVITY_STATUS.未开始, ACTIVITY_STATUS.已下架, ACTIVITY_STATUS.已结束],
  239. 查看拒绝原因: [ACTIVITY_STATUS.审核驳回],
  240. 上传活动结果: [ACTIVITY_STATUS.已结束]
  241. } as const;
  242. // 判断按钮是否显示的工具函数
  243. const canShowButton = (status: number, allowedStatuses: readonly number[]) => {
  244. return allowedStatuses.includes(status);
  245. };
  246. // 判断活动是否已上传结果
  247. const hasUploadedResult = (row: any) => {
  248. // 检查是否有结果标识字段(可能的后端返回字段名:hasResult, resultUploaded, achievementUploaded, resultId等)
  249. // 或者检查是否有结果内容字段(resultText, resultMediaUrl等)
  250. return !!(
  251. row.hasResult ||
  252. row.resultUploaded ||
  253. row.achievementUploaded ||
  254. row.resultId ||
  255. row.resultText ||
  256. row.resultMediaUrl ||
  257. row.achievementDesc ||
  258. row.mediaUrls
  259. );
  260. };
  261. // 获取状态标签
  262. const getStatusLabel = (status: number) => {
  263. const statusMap: Record<number, string> = {
  264. 1: "待审核",
  265. 2: "未开始",
  266. 3: "审核驳回",
  267. 5: "进行中",
  268. 6: "已下架",
  269. 7: "已结束",
  270. 8: "审核通过"
  271. };
  272. return statusMap[status] || "--";
  273. };
  274. // 表格列配置
  275. const columns = reactive<ColumnProps<any>[]>([
  276. {
  277. prop: "activityName",
  278. label: "活动名称",
  279. search: {
  280. el: "input",
  281. props: { placeholder: "请输入" }
  282. }
  283. },
  284. {
  285. prop: "id",
  286. label: "活动ID"
  287. },
  288. {
  289. prop: "activityType",
  290. label: "活动类型",
  291. width: 120,
  292. enum: activityTypeEnum,
  293. fieldNames: { label: "label", value: "value" },
  294. search: {
  295. el: "select",
  296. props: { placeholder: "请选择所属活动" },
  297. order: 1
  298. },
  299. render: (scope: any) => {
  300. // 兼容旧数据:如果后端返回的是数字,转换为字符串
  301. const activityType = scope.row.activityType;
  302. if (activityType == 1 || activityType == "1") {
  303. return "营销活动";
  304. } else if (activityType == 2 || activityType == "2") {
  305. return "评论有礼";
  306. }
  307. return activityType == "MARKETING" ? "营销活动" : "评论有礼";
  308. }
  309. },
  310. {
  311. prop: "signupStartTime",
  312. label: "报名开始时间/结束时间",
  313. width: 300,
  314. render: (scope: any) => {
  315. const formatDate = (dateStr: string) => {
  316. if (!dateStr) return "--";
  317. // 只取日期部分(去掉时分秒)
  318. const datePart = dateStr.split(" ")[0];
  319. return datePart?.replace(/-/g, "/") || "--";
  320. };
  321. return `${formatDate(scope.row.signupStartTime)} - ${formatDate(scope.row.signupEndTime)}`;
  322. }
  323. },
  324. {
  325. prop: "startTime",
  326. label: "活动开始时间/结束时间",
  327. width: 300,
  328. render: (scope: any) => {
  329. const formatDate = (dateStr: string) => {
  330. if (!dateStr) return "--";
  331. // 只取日期部分(去掉时分秒)
  332. const datePart = dateStr.split(" ")[0];
  333. return datePart?.replace(/-/g, "/") || "--";
  334. };
  335. return `${formatDate(scope.row.startTime)} - ${formatDate(scope.row.endTime)}`;
  336. }
  337. },
  338. {
  339. prop: "status",
  340. label: "状态",
  341. render: (scope: any) => {
  342. // 优先使用返回的 statusName,如果没有则使用 getStatusLabel
  343. return scope.row.statusName || getStatusLabel(scope.row.status);
  344. },
  345. search: {
  346. el: "select",
  347. props: { placeholder: "请选择" }
  348. },
  349. enum: statusEnum,
  350. fieldNames: { label: "label", value: "value" }
  351. },
  352. { prop: "operation", label: "操作", fixed: "right", width: 300 }
  353. ]);
  354. // 初始化请求参数
  355. const initParam = reactive({
  356. storeId: localGet("createdId")
  357. });
  358. // 数据回调处理
  359. const dataCallback = (data: any) => {
  360. return {
  361. list: data?.records || [],
  362. total: data?.total || 0
  363. };
  364. };
  365. // 获取表格列表
  366. const getTableList = async (params: any) => {
  367. // 显示全屏loading
  368. const loadingInstance = ElLoading.service({
  369. lock: true,
  370. text: "加载中...",
  371. background: "rgba(0, 0, 0, 0.7)"
  372. });
  373. try {
  374. // 处理参数:确保 status 是 number 类型,pageNum 和 pageSize 转换为 string
  375. const newParams: any = {
  376. ...params,
  377. pageNum: params.pageNum ? String(params.pageNum) : undefined,
  378. pageSize: params.pageSize ? String(params.pageSize) : undefined,
  379. status: params.status !== undefined && params.status !== null && params.status !== "" ? Number(params.status) : undefined,
  380. storeId: params.storeId ? String(params.storeId) : undefined,
  381. // 处理 activityType:如果存在且不为空,保持字符串类型('MARKETING' 或 'COMMENT')
  382. activityType:
  383. params.activityType !== undefined && params.activityType !== null && params.activityType !== ""
  384. ? String(params.activityType)
  385. : undefined
  386. };
  387. const result = await getActivityList(newParams);
  388. return result;
  389. } finally {
  390. // 关闭loading
  391. loadingInstance.close();
  392. }
  393. };
  394. // 新建活动
  395. const newActivity = () => {
  396. router.push(`/operationManagement/newActivity?type=add`);
  397. };
  398. // 跳转详情页
  399. const toDetail = (row: any) => {
  400. router.push(`/operationManagement/activityDetail?id=${row.id}`);
  401. };
  402. // 编辑行数据
  403. const editRow = (row: any) => {
  404. router.push(`/operationManagement/newActivity?id=${row.id}&type=edit`);
  405. };
  406. // 删除行数据
  407. const deleteRow = (row: any) => {
  408. ElMessageBox.confirm("确定要删除吗?", "提示", {
  409. confirmButtonText: "确定",
  410. cancelButtonText: "取消",
  411. type: "warning"
  412. })
  413. .then(() => {
  414. const params = {
  415. id: row.id
  416. };
  417. return deleteActivity(params);
  418. })
  419. .then(() => {
  420. ElMessage.success("删除成功");
  421. proTable.value?.getTableList();
  422. })
  423. .catch(() => {
  424. // 用户取消删除,不做任何操作
  425. });
  426. };
  427. // 修改状态(上架/下架)
  428. const changeStatus = async (row: any, status: number) => {
  429. const res: any = await updateActivityStatus({ id: row.id, status: status });
  430. if (res && (res.code === 200 || res.code === "200")) {
  431. ElMessage.success("操作成功");
  432. proTable.value?.getTableList();
  433. }
  434. };
  435. // 查看拒绝原因
  436. const viewRejectReason = (row: any) => {
  437. rejectReasonData.value = {
  438. name: row.activityName,
  439. approvalComments: row.approvalComments
  440. };
  441. rejectReasonDialogVisible.value = true;
  442. };
  443. // 关闭拒绝原因弹窗
  444. const closeRejectReasonDialog = () => {
  445. rejectReasonDialogVisible.value = false;
  446. };
  447. // 打开上传活动结果抽屉
  448. const openUploadResultDrawer = (row: any) => {
  449. currentActivityId.value = Number(row.id);
  450. uploadResultForm.value = {
  451. resultType: 0, // 默认选择文字
  452. resultText: "",
  453. resultMediaUrl: ""
  454. };
  455. resultImageFileList.value = [];
  456. uploadResultDrawerVisible.value = true;
  457. };
  458. // 关闭上传活动结果抽屉
  459. const closeUploadResultDrawer = () => {
  460. uploadResultDrawerVisible.value = false;
  461. uploadResultForm.value = {
  462. resultType: 0, // 默认选择文字
  463. resultText: "",
  464. resultMediaUrl: ""
  465. };
  466. resultImageFileList.value = [];
  467. };
  468. // 处理活动结果图片变更
  469. const handleResultImageChange: UploadProps["onChange"] = async (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  470. if (uploadFile.raw) {
  471. const fileType = uploadFile.raw.type.toLowerCase();
  472. const fileName = uploadFile.name.toLowerCase();
  473. const validTypes = ["image/jpeg", "image/jpg", "image/png"];
  474. const validExtensions = [".jpg", ".jpeg", ".png"];
  475. const isValidType = validTypes.includes(fileType) || validExtensions.some(ext => fileName.endsWith(ext));
  476. if (!isValidType) {
  477. ElMessage.warning("只支持上传 JPG、JPEG 和 PNG 格式的图片");
  478. const index = resultImageFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
  479. if (index > -1) {
  480. resultImageFileList.value.splice(index, 1);
  481. }
  482. return;
  483. }
  484. const maxSize = 20 * 1024 * 1024; // 20MB
  485. if (uploadFile.raw.size > maxSize) {
  486. ElMessage.warning("上传图片不得超过20M");
  487. const index = resultImageFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
  488. if (index > -1) {
  489. resultImageFileList.value.splice(index, 1);
  490. }
  491. return;
  492. }
  493. // 确保文件在列表中
  494. const existingIndex = resultImageFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
  495. if (existingIndex === -1) {
  496. resultImageFileList.value.push(uploadFile);
  497. }
  498. // 自动上传图片
  499. try {
  500. uploadFile.status = "uploading";
  501. uploadFile.percentage = 0;
  502. const formData = new FormData();
  503. formData.append("file", uploadFile.raw);
  504. formData.append("user", "text");
  505. const res: any = await uploadContractImage(formData);
  506. if (res?.code === 200 && res.data) {
  507. const imageUrl = res.data[0];
  508. if (imageUrl) {
  509. uploadFile.status = "success";
  510. uploadFile.percentage = 100;
  511. uploadFile.url = imageUrl;
  512. uploadFile.response = { url: imageUrl };
  513. uploadResultForm.value.resultMediaUrl = imageUrl;
  514. // 触发视图更新
  515. resultImageFileList.value = [...resultImageFileList.value];
  516. } else {
  517. throw new Error("上传失败:未获取到图片URL");
  518. }
  519. } else {
  520. throw new Error(res?.msg || "图片上传失败");
  521. }
  522. } catch (error: any) {
  523. uploadFile.status = "fail";
  524. uploadFile.percentage = 0;
  525. ElMessage.error(error?.message || "图片上传失败,请重试");
  526. const index = resultImageFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
  527. if (index > -1) {
  528. resultImageFileList.value.splice(index, 1);
  529. }
  530. }
  531. }
  532. };
  533. // 处理活动结果图片超出限制
  534. const handleResultImageExceed: UploadProps["onExceed"] = () => {
  535. ElMessage.warning("最多只能上传1张图片");
  536. };
  537. // 预览活动结果图片
  538. const handleResultImagePreview: UploadProps["onPreview"] = (uploadFile: UploadFile) => {
  539. const response = uploadFile.response as any;
  540. const url = uploadFile.url || response?.url || (Array.isArray(response?.data) ? response.data[0] : null);
  541. if (url) {
  542. resultImageViewerUrlList.value = [url];
  543. resultImageViewerInitialIndex.value = 0;
  544. resultImageViewerVisible.value = true;
  545. }
  546. };
  547. // 删除活动结果图片前确认
  548. const handleResultImageBeforeRemove: UploadProps["beforeRemove"] = async () => {
  549. try {
  550. await ElMessageBox.confirm("确定要删除这张图片吗?", "提示", {
  551. confirmButtonText: "确定",
  552. cancelButtonText: "取消",
  553. type: "warning"
  554. });
  555. return true;
  556. } catch {
  557. return false;
  558. }
  559. };
  560. // 删除活动结果图片
  561. const handleResultImageRemove: UploadProps["onRemove"] = () => {
  562. uploadResultForm.value.resultMediaUrl = "";
  563. ElMessage.success("图片已删除");
  564. };
  565. // 提交上传活动结果
  566. const submitUploadResult = async () => {
  567. // 验证必填字段
  568. if (uploadResultForm.value.resultType === 0) {
  569. // 文字类型
  570. if (!uploadResultForm.value.resultText || uploadResultForm.value.resultText.trim() === "") {
  571. ElMessage.warning("请输入文字内容");
  572. return;
  573. }
  574. } else if (uploadResultForm.value.resultType === 1) {
  575. // 图片类型
  576. if (!uploadResultForm.value.resultMediaUrl) {
  577. ElMessage.warning("请上传图片");
  578. return;
  579. }
  580. }
  581. try {
  582. uploadResultSubmitting.value = true;
  583. const params: any = {
  584. id: currentActivityId.value, // 活动ID
  585. resultType: uploadResultForm.value.resultType, // 0-文字,1-图片
  586. resultText: uploadResultForm.value.resultType === 0 ? uploadResultForm.value.resultText : undefined,
  587. resultMediaUrl: uploadResultForm.value.resultType === 1 ? uploadResultForm.value.resultMediaUrl : undefined
  588. };
  589. const res: any = await uploadActivityResult(params);
  590. if (res.code == 200) {
  591. ElMessage.success("上传成功");
  592. closeUploadResultDrawer();
  593. proTable.value?.getTableList();
  594. } else {
  595. ElMessage.error(res?.msg || "上传失败");
  596. }
  597. } catch (error) {
  598. console.error("上传活动结果失败:", error);
  599. ElMessage.error("上传失败,请重试");
  600. } finally {
  601. uploadResultSubmitting.value = false;
  602. }
  603. };
  604. // 页面加载时触发查询
  605. onMounted(async () => {
  606. type.value = await usePermission("新建运营活动");
  607. proTable.value?.getTableList();
  608. });
  609. </script>
  610. <style lang="scss" scoped>
  611. .action-buttons {
  612. display: flex;
  613. flex: 0 0 auto;
  614. gap: 10px;
  615. margin-right: 20px;
  616. .button {
  617. margin-bottom: 0;
  618. }
  619. }
  620. .reject-reason-content {
  621. padding: 20px 0;
  622. .reject-reason-item {
  623. display: flex;
  624. margin-bottom: 20px;
  625. &:last-child {
  626. margin-bottom: 0;
  627. }
  628. .reject-reason-label {
  629. flex-shrink: 0;
  630. min-width: 100px;
  631. font-size: 14px;
  632. font-weight: 500;
  633. color: #606266;
  634. }
  635. .reject-reason-value {
  636. flex: 1;
  637. font-size: 14px;
  638. color: #303133;
  639. word-break: break-word;
  640. &.reject-reason-text {
  641. min-height: 80px;
  642. padding: 12px;
  643. line-height: 1.6;
  644. white-space: pre-wrap;
  645. background-color: #f5f7fa;
  646. border-radius: 4px;
  647. }
  648. }
  649. }
  650. }
  651. // 上传活动结果抽屉样式
  652. .upload-result-content {
  653. padding: 20px 0;
  654. .result-type-section {
  655. margin-bottom: 24px;
  656. .result-type-label {
  657. margin-bottom: 12px;
  658. font-size: 14px;
  659. font-weight: 500;
  660. color: #606266;
  661. }
  662. }
  663. .result-content-section {
  664. .result-content-label {
  665. margin-bottom: 12px;
  666. font-size: 14px;
  667. font-weight: 500;
  668. color: #606266;
  669. }
  670. .upload-area-wrapper {
  671. // 当有文件时,隐藏上传框
  672. &.has-file {
  673. :deep(.el-upload--picture-card) {
  674. display: none !important;
  675. }
  676. }
  677. }
  678. }
  679. }
  680. .drawer-footer {
  681. display: flex;
  682. gap: 12px;
  683. justify-content: flex-end;
  684. }
  685. </style>