activityList.vue 20 KB

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