|
|
@@ -0,0 +1,634 @@
|
|
|
+<template>
|
|
|
+ <div class="publish-dynamic-container">
|
|
|
+ <!-- 头部导航 -->
|
|
|
+ <div class="header-bar">
|
|
|
+ <div class="header-left">
|
|
|
+ <el-button text @click="handleGoBack">
|
|
|
+ <el-icon :size="20">
|
|
|
+ <ArrowLeft />
|
|
|
+ </el-icon>
|
|
|
+ 返回
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ <div class="header-title">发布动态</div>
|
|
|
+ <div class="header-right" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 表单内容 -->
|
|
|
+ <div class="form-container">
|
|
|
+ <el-form ref="formRef" :model="formData" :rules="rules" label-position="top">
|
|
|
+ <!-- 图片上传 -->
|
|
|
+ <el-form-item label="图片" prop="images">
|
|
|
+ <div class="upload-section">
|
|
|
+ <el-upload
|
|
|
+ v-model:file-list="fileList"
|
|
|
+ list-type="picture-card"
|
|
|
+ :limit="20"
|
|
|
+ :on-preview="handlePicturePreview"
|
|
|
+ :on-remove="handleRemoveImage"
|
|
|
+ :on-change="handleFileChange"
|
|
|
+ :before-upload="beforeImageUpload"
|
|
|
+ :http-request="handleImageUpload"
|
|
|
+ accept="image/*"
|
|
|
+ multiple
|
|
|
+ class="dynamic-upload"
|
|
|
+ >
|
|
|
+ <div class="upload-trigger">
|
|
|
+ <el-icon :size="32" color="#999">
|
|
|
+ <Plus />
|
|
|
+ </el-icon>
|
|
|
+ <div class="upload-count">({{ fileList.length }}/20)</div>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 标题 -->
|
|
|
+ <el-form-item label="标题" prop="title">
|
|
|
+ <el-input v-model="formData.title" placeholder="请输入标题" maxlength="50" show-word-limit size="large" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 正文 -->
|
|
|
+ <el-form-item label="正文" prop="content">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.content"
|
|
|
+ type="textarea"
|
|
|
+ placeholder="请输入正文"
|
|
|
+ :rows="8"
|
|
|
+ maxlength="500"
|
|
|
+ show-word-limit
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 位置 -->
|
|
|
+ <el-form-item label="位置" prop="location">
|
|
|
+ <el-input v-model="formData.location" placeholder="请选择或许位置" size="large" readonly @click="handleSelectLocation">
|
|
|
+ <template #suffix>
|
|
|
+ <el-icon color="#999">
|
|
|
+ <Location />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 底部操作按钮 -->
|
|
|
+ <div class="footer-actions">
|
|
|
+ <el-button size="large" class="draft-btn" @click="handleSaveDraft"> 保存草稿 </el-button>
|
|
|
+ <el-button type="primary" size="large" class="publish-btn" :loading="publishing" @click="handlePublish"> 发布 </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 图片预览对话框 -->
|
|
|
+ <el-dialog v-model="previewDialogVisible" width="800px" append-to-body>
|
|
|
+ <img :src="previewImageUrl" alt="预览图片" style="width: 100%" />
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 位置选择对话框 -->
|
|
|
+ <el-dialog v-model="locationDialogVisible" title="选择位置" width="500px" append-to-body>
|
|
|
+ <el-input v-model="locationSearch" placeholder="搜索位置" clearable @input="handleSearchLocation">
|
|
|
+ <template #prefix>
|
|
|
+ <el-icon>
|
|
|
+ <Search />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <div class="location-list">
|
|
|
+ <div v-for="location in locationList" :key="location.id" class="location-item" @click="handleChooseLocation(location)">
|
|
|
+ <el-icon>
|
|
|
+ <Location />
|
|
|
+ </el-icon>
|
|
|
+ <span>{{ location.name }}</span>
|
|
|
+ </div>
|
|
|
+ <el-empty v-if="locationList.length === 0" description="暂无位置信息" />
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, reactive, onMounted } from "vue";
|
|
|
+import { useRouter } from "vue-router";
|
|
|
+import { ElMessage, ElMessageBox } from "element-plus";
|
|
|
+import { ArrowLeft, Plus, Location, Search } from "@element-plus/icons-vue";
|
|
|
+import type { FormInstance, FormRules, UploadUserFile, UploadFile } from "element-plus";
|
|
|
+// import { publishDynamic, saveDraft, uploadDynamicImage } from "@/api/modules/dynamicManagement";
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+// 接口定义
|
|
|
+interface FormData {
|
|
|
+ title: string;
|
|
|
+ content: string;
|
|
|
+ images: string[];
|
|
|
+ location: string;
|
|
|
+ locationId?: string;
|
|
|
+}
|
|
|
+
|
|
|
+interface LocationItem {
|
|
|
+ id: string;
|
|
|
+ name: string;
|
|
|
+ address: string;
|
|
|
+}
|
|
|
+
|
|
|
+// 响应式数据
|
|
|
+const formRef = ref<FormInstance>();
|
|
|
+const fileList = ref<UploadUserFile[]>([]);
|
|
|
+const previewDialogVisible = ref(false);
|
|
|
+const previewImageUrl = ref("");
|
|
|
+const locationDialogVisible = ref(false);
|
|
|
+const locationSearch = ref("");
|
|
|
+const locationList = ref<LocationItem[]>([]);
|
|
|
+const publishing = ref(false);
|
|
|
+const pendingUploadFiles = ref<UploadFile[]>([]);
|
|
|
+const uploading = ref(false);
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const formData = reactive<FormData>({
|
|
|
+ title: "",
|
|
|
+ content: "",
|
|
|
+ images: [],
|
|
|
+ location: ""
|
|
|
+});
|
|
|
+
|
|
|
+// 表单验证规则
|
|
|
+const rules = reactive<FormRules<FormData>>({
|
|
|
+ title: [{ required: true, message: "请输入标题", trigger: "blur" }],
|
|
|
+ content: [{ required: true, message: "请输入正文", trigger: "blur" }]
|
|
|
+});
|
|
|
+
|
|
|
+// 返回上一页
|
|
|
+const handleGoBack = async () => {
|
|
|
+ // 检查是否有未保存的内容
|
|
|
+ if (formData.title || formData.content || fileList.value.length > 0) {
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm("当前有未保存的内容,确定要离开吗?", "提示", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ });
|
|
|
+ router.back();
|
|
|
+ } catch {
|
|
|
+ // 用户取消
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ router.back();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 文件改变
|
|
|
+const handleFileChange = (uploadFile: UploadFile, uploadFiles: UploadFile[]) => {
|
|
|
+ // 验证文件
|
|
|
+ if (uploadFile.raw) {
|
|
|
+ const isImage = uploadFile.raw.type.startsWith("image/");
|
|
|
+ if (!isImage) {
|
|
|
+ const index = uploadFiles.findIndex(f => f.uid === uploadFile.uid);
|
|
|
+ if (index > -1) {
|
|
|
+ uploadFiles.splice(index, 1);
|
|
|
+ }
|
|
|
+ ElMessage.warning("只能上传图片文件");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const isLt20M = uploadFile.raw.size / 1024 / 1024 < 20;
|
|
|
+ if (!isLt20M) {
|
|
|
+ const index = uploadFiles.findIndex(f => f.uid === uploadFile.uid);
|
|
|
+ if (index > -1) {
|
|
|
+ uploadFiles.splice(index, 1);
|
|
|
+ }
|
|
|
+ ElMessage.warning("图片大小不能超过 20MB");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加到待上传队列
|
|
|
+ const existingIndex = fileList.value.findIndex(f => f.uid === uploadFile.uid);
|
|
|
+ if (existingIndex === -1 && uploadFile.status) {
|
|
|
+ fileList.value.push(uploadFile as UploadUserFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ const readyFiles = fileList.value.filter(file => file.status === "ready");
|
|
|
+ if (readyFiles.length) {
|
|
|
+ readyFiles.forEach(file => {
|
|
|
+ if (!pendingUploadFiles.value.some(item => item.uid === file.uid)) {
|
|
|
+ pendingUploadFiles.value.push(file as UploadFile);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ processUploadQueue();
|
|
|
+};
|
|
|
+
|
|
|
+// 处理上传队列
|
|
|
+const processUploadQueue = async () => {
|
|
|
+ if (uploading.value || pendingUploadFiles.value.length === 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const file = pendingUploadFiles.value.shift();
|
|
|
+ if (file) {
|
|
|
+ await uploadSingleFile(file);
|
|
|
+ processUploadQueue();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 单个文件上传
|
|
|
+const uploadSingleFile = async (file: UploadFile) => {
|
|
|
+ if (!file.raw) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const rawFile = file.raw as File;
|
|
|
+ const uploadFormData = new FormData();
|
|
|
+ uploadFormData.append("file", rawFile);
|
|
|
+
|
|
|
+ file.status = "uploading";
|
|
|
+ file.percentage = 0;
|
|
|
+ uploading.value = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // TODO: 集成真实上传接口时,取消下面的注释
|
|
|
+ // const result = await uploadDynamicImage(uploadFormData);
|
|
|
+ // if (result?.code === 200 && result.data) {
|
|
|
+ // const imageUrl = result.data.url;
|
|
|
+ // file.status = "success";
|
|
|
+ // file.percentage = 100;
|
|
|
+ // file.url = imageUrl;
|
|
|
+ // file.response = { url: imageUrl };
|
|
|
+ // if (!formData.images.includes(imageUrl)) {
|
|
|
+ // formData.images.push(imageUrl);
|
|
|
+ // }
|
|
|
+ // } else {
|
|
|
+ // throw new Error(result?.msg || "图片上传失败");
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 临时方案:使用 FileReader 模拟上传
|
|
|
+ await new Promise<void>((resolve, reject) => {
|
|
|
+ const reader = new FileReader();
|
|
|
+ reader.onload = e => {
|
|
|
+ const imageUrl = e.target?.result as string;
|
|
|
+ file.status = "success";
|
|
|
+ file.percentage = 100;
|
|
|
+ file.url = imageUrl;
|
|
|
+ file.response = { url: imageUrl };
|
|
|
+ if (!formData.images.includes(imageUrl)) {
|
|
|
+ formData.images.push(imageUrl);
|
|
|
+ }
|
|
|
+ resolve();
|
|
|
+ };
|
|
|
+ reader.onerror = () => reject(new Error("读取文件失败"));
|
|
|
+ reader.readAsDataURL(rawFile);
|
|
|
+ });
|
|
|
+ } catch (error: any) {
|
|
|
+ file.status = "fail";
|
|
|
+ if (file.url && file.url.startsWith("blob:")) {
|
|
|
+ URL.revokeObjectURL(file.url);
|
|
|
+ }
|
|
|
+ const index = fileList.value.findIndex(f => f.uid === file.uid);
|
|
|
+ if (index > -1) {
|
|
|
+ fileList.value.splice(index, 1);
|
|
|
+ }
|
|
|
+ ElMessage.error(error?.message || "图片上传失败");
|
|
|
+ } finally {
|
|
|
+ uploading.value = false;
|
|
|
+ fileList.value = [...fileList.value];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 图片上传前验证
|
|
|
+const beforeImageUpload = (file: File) => {
|
|
|
+ const isImage = file.type.startsWith("image/");
|
|
|
+ const isLt20M = file.size / 1024 / 1024 < 20;
|
|
|
+
|
|
|
+ if (!isImage) {
|
|
|
+ ElMessage.error("只能上传图片文件!");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!isLt20M) {
|
|
|
+ ElMessage.error("图片大小不能超过 20MB!");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+};
|
|
|
+
|
|
|
+// 自定义上传
|
|
|
+const handleImageUpload = async (options: any) => {
|
|
|
+ // 上传逻辑已在 uploadSingleFile 中处理
|
|
|
+ return;
|
|
|
+};
|
|
|
+
|
|
|
+// 图片预览
|
|
|
+const handlePicturePreview = (uploadFile: UploadUserFile) => {
|
|
|
+ previewImageUrl.value = uploadFile.url!;
|
|
|
+ previewDialogVisible.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+// 移除图片
|
|
|
+const handleRemoveImage = (uploadFile: UploadUserFile, uploadFiles: UploadUserFile[]) => {
|
|
|
+ const index = formData.images.findIndex(url => url === uploadFile.url);
|
|
|
+ if (index > -1) {
|
|
|
+ formData.images.splice(index, 1);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 选择位置
|
|
|
+const handleSelectLocation = () => {
|
|
|
+ locationDialogVisible.value = true;
|
|
|
+ // 加载位置列表
|
|
|
+ loadLocationList();
|
|
|
+};
|
|
|
+
|
|
|
+// 搜索位置
|
|
|
+const handleSearchLocation = () => {
|
|
|
+ // TODO: 实现位置搜索
|
|
|
+ loadLocationList(locationSearch.value);
|
|
|
+};
|
|
|
+
|
|
|
+// 加载位置列表
|
|
|
+const loadLocationList = (keyword?: string) => {
|
|
|
+ // TODO: 集成真实接口
|
|
|
+ // 模拟数据
|
|
|
+ const mockLocations: LocationItem[] = [
|
|
|
+ { id: "1", name: "天安门广场", address: "北京市东城区" },
|
|
|
+ { id: "2", name: "故宫博物院", address: "北京市东城区景山前街4号" },
|
|
|
+ { id: "3", name: "颐和园", address: "北京市海淀区新建宫门路19号" },
|
|
|
+ { id: "4", name: "长城", address: "北京市延庆区" },
|
|
|
+ { id: "5", name: "鸟巢", address: "北京市朝阳区国家体育场南路1号" }
|
|
|
+ ];
|
|
|
+
|
|
|
+ if (keyword) {
|
|
|
+ locationList.value = mockLocations.filter(loc => loc.name.includes(keyword) || loc.address.includes(keyword));
|
|
|
+ } else {
|
|
|
+ locationList.value = mockLocations;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 选择位置
|
|
|
+const handleChooseLocation = (location: LocationItem) => {
|
|
|
+ formData.location = location.name;
|
|
|
+ formData.locationId = location.id;
|
|
|
+ locationDialogVisible.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+// 保存草稿
|
|
|
+const handleSaveDraft = async () => {
|
|
|
+ if (!formData.title && !formData.content && fileList.value.length === 0) {
|
|
|
+ ElMessage.warning("请至少填写标题或正文");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // TODO: 集成真实接口时,取消下面的注释
|
|
|
+ // await saveDraft({
|
|
|
+ // title: formData.title,
|
|
|
+ // content: formData.content,
|
|
|
+ // images: formData.images,
|
|
|
+ // location: formData.location,
|
|
|
+ // locationId: formData.locationId
|
|
|
+ // });
|
|
|
+
|
|
|
+ ElMessage.success("草稿保存成功");
|
|
|
+ router.back();
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("保存草稿失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 发布动态
|
|
|
+const handlePublish = async () => {
|
|
|
+ if (!formRef.value) return;
|
|
|
+
|
|
|
+ await formRef.value.validate(async (valid: boolean) => {
|
|
|
+ if (valid) {
|
|
|
+ // 检查是否有图片正在上传
|
|
|
+ if (uploading.value || pendingUploadFiles.value.length > 0) {
|
|
|
+ ElMessage.warning("图片正在上传中,请稍候...");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ publishing.value = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // TODO: 集成真实接口时,取消下面的注释
|
|
|
+ // await publishDynamic({
|
|
|
+ // title: formData.title,
|
|
|
+ // content: formData.content,
|
|
|
+ // images: formData.images,
|
|
|
+ // location: formData.location,
|
|
|
+ // locationId: formData.locationId
|
|
|
+ // });
|
|
|
+
|
|
|
+ // 模拟发布延迟
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
+
|
|
|
+ ElMessage.success("发布成功");
|
|
|
+ router.back();
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("发布失败");
|
|
|
+ } finally {
|
|
|
+ publishing.value = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 初始化
|
|
|
+onMounted(() => {
|
|
|
+ // 可以在这里加载草稿数据
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.publish-dynamic-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ min-height: 100vh;
|
|
|
+ background: #f5f7fa;
|
|
|
+
|
|
|
+ // 头部导航
|
|
|
+ .header-bar {
|
|
|
+ position: sticky;
|
|
|
+ top: 0;
|
|
|
+ z-index: 100;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ height: 60px;
|
|
|
+ padding: 0 20px;
|
|
|
+ background: #ffffff;
|
|
|
+ box-shadow: 0 2px 4px rgb(0 0 0 / 5%);
|
|
|
+ .header-left {
|
|
|
+ flex: 1;
|
|
|
+ :deep(.el-button) {
|
|
|
+ padding: 8px 0;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #606266;
|
|
|
+ &:hover {
|
|
|
+ color: #409eff;
|
|
|
+ }
|
|
|
+ .el-icon {
|
|
|
+ margin-right: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .header-title {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .header-right {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 表单容器
|
|
|
+ .form-container {
|
|
|
+ flex: 1;
|
|
|
+ width: 100%;
|
|
|
+ max-width: 800px;
|
|
|
+ padding: 30px 20px 100px;
|
|
|
+ margin: 0 auto;
|
|
|
+ :deep(.el-form) {
|
|
|
+ .el-form-item {
|
|
|
+ margin-bottom: 30px;
|
|
|
+ .el-form-item__label {
|
|
|
+ padding-bottom: 12px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 图片上传区域
|
|
|
+ .upload-section {
|
|
|
+ :deep(.el-upload-list) {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+ :deep(.el-upload--picture-card) {
|
|
|
+ width: 148px;
|
|
|
+ height: 148px;
|
|
|
+ border: 2px dashed #dcdfe6;
|
|
|
+ border-radius: 8px;
|
|
|
+ transition: all 0.3s;
|
|
|
+ &:hover {
|
|
|
+ border-color: #409eff;
|
|
|
+ }
|
|
|
+ .upload-trigger {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 100%;
|
|
|
+ .upload-count {
|
|
|
+ margin-top: 8px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ :deep(.el-upload-list--picture-card .el-upload-list__item) {
|
|
|
+ width: 148px;
|
|
|
+ height: 148px;
|
|
|
+ margin: 0;
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 输入框样式
|
|
|
+ :deep(.el-input__inner),
|
|
|
+ :deep(.el-textarea__inner) {
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
+ :deep(.el-textarea__inner) {
|
|
|
+ padding: 12px 15px;
|
|
|
+ font-size: 15px;
|
|
|
+ line-height: 1.6;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 底部操作按钮
|
|
|
+ .footer-actions {
|
|
|
+ position: fixed;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ z-index: 99;
|
|
|
+ display: flex;
|
|
|
+ gap: 16px;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 16px 20px;
|
|
|
+ background: #ffffff;
|
|
|
+ box-shadow: 0 -2px 8px rgb(0 0 0 / 8%);
|
|
|
+ .el-button {
|
|
|
+ min-width: 180px;
|
|
|
+ height: 48px;
|
|
|
+ font-size: 16px;
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
+ .draft-btn {
|
|
|
+ color: #606266;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-color: #dcdfe6;
|
|
|
+ &:hover {
|
|
|
+ color: #409eff;
|
|
|
+ background: #ecf5ff;
|
|
|
+ border-color: #409eff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .publish-btn {
|
|
|
+ background: #409eff;
|
|
|
+ border-color: #409eff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 位置选择对话框
|
|
|
+ :deep(.el-dialog) {
|
|
|
+ border-radius: 12px;
|
|
|
+ .location-list {
|
|
|
+ max-height: 400px;
|
|
|
+ margin-top: 16px;
|
|
|
+ overflow-y: auto;
|
|
|
+ .location-item {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ align-items: center;
|
|
|
+ padding: 12px 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ border-radius: 8px;
|
|
|
+ transition: all 0.3s;
|
|
|
+ &:hover {
|
|
|
+ background: #f5f7fa;
|
|
|
+ }
|
|
|
+ .el-icon {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+ span {
|
|
|
+ font-size: 15px;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 响应式适配
|
|
|
+@media (width <= 768px) {
|
|
|
+ .publish-dynamic-container {
|
|
|
+ .form-container {
|
|
|
+ padding: 20px 16px 100px;
|
|
|
+ }
|
|
|
+ .footer-actions {
|
|
|
+ padding: 12px 16px;
|
|
|
+ .el-button {
|
|
|
+ min-width: 140px;
|
|
|
+ height: 44px;
|
|
|
+ font-size: 15px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|