| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- <!-- 合伙人推广海报编辑 -->
- <template>
- <el-dialog
- :title="editForm.id ? '编辑海报' : '新增海报'"
- v-model="visible"
- width="1000px"
- @closed="resetForm"
- >
- <div class="poster-edit-container">
- <!-- 左侧手机预览 -->
- <div class="mobile-preview">
- <div class="preview-content">
- <div class="preview-poster" v-if="editForm.background">
- <el-image
- :src="editForm.background"
- fit="cover"
- style="width: 250px; height: 445px"
- />
- <!-- 头像预览 -->
- <div
- class="avatar-preview"
- v-if="editForm.headImgPosX && editForm.headImgPosY"
- :style="{
- left: editForm.headImgPosX + 'px',
- top: editForm.headImgPosY + 'px',
- width: '30px',
- height: '30px',
- borderRadius: '50%',
- background: '#e0e0e0',
- position: 'absolute'
- }"
- ></div>
- <!-- 昵称预览 -->
- <div
- class="nickname-preview"
- v-if="
- editForm.nickNamePosX && editForm.nickNamePosY
- "
- :style="{
- left: editForm.nickNamePosX + 'px',
- top: editForm.nickNamePosY + 'px',
- position: 'absolute',
- color: '#333',
- fontSize: '14px'
- }"
- >微信昵称</div
- >
- <!-- 二维码预览 -->
- <div
- class="qrcode-preview"
- v-if="
- editForm.qrCodePosX &&
- editForm.qrCodePosY &&
- editForm.qrCodeWidth &&
- editForm.qrCodeHeight
- "
- :style="{
- left: editForm.qrCodePosX + 'px',
- top: editForm.qrCodePosY + 'px',
- width: editForm.qrCodeWidth + 'px',
- height: editForm.qrCodeHeight + 'px',
- background: '#e0e0e0',
- position: 'absolute',
- borderRadius: '50%'
- }"
- ></div>
- </div>
- </div>
- </div>
- <!-- 右侧编辑表单 -->
- <div class="edit-form">
- <el-form
- ref="formRef"
- :model="editForm"
- :rules="rules"
- label-width="100px"
- >
- <el-form-item label="模板名称" prop="name">
- <el-input
- v-model="editForm.name"
- placeholder="请输入模板名称"
- />
- </el-form-item>
- <el-form-item label="背景图片" prop="background">
- <image-upload
- v-model="editForm.background"
- :limit="1"
- />
- <div class="upload-tip">建议尺寸: 750 x 1334px</div>
- </el-form-item>
- <el-form-item label="微信头像位置">
- <el-row :gutter="10">
- <el-col :span="12">
- <span>X</span>
- <el-input-number
- v-model="editForm.headImgPosX"
- :min="0"
- :precision="0"
- :step="1"
- controls-position="right"
- placeholder="X"
- />
- </el-col>
- <el-col :span="12">
- <span>Y</span>
- <el-input-number
- v-model="editForm.headImgPosY"
- :min="0"
- :precision="0"
- :step="1"
- controls-position="right"
- placeholder="Y"
- />
- </el-col>
- </el-row>
- </el-form-item>
- <el-form-item label="微信名位置">
- <el-row :gutter="10">
- <el-col :span="12">
- <span>X</span>
- <el-input-number
- v-model="editForm.nickNamePosX"
- :min="0"
- :precision="0"
- :step="1"
- controls-position="right"
- placeholder="X"
- />
- </el-col>
- <el-col :span="12">
- <span>Y</span>
- <el-input-number
- v-model="editForm.nickNamePosY"
- :min="0"
- :precision="0"
- :step="1"
- controls-position="right"
- placeholder="Y"
- />
- </el-col>
- </el-row>
- </el-form-item>
- <el-form-item label="二维码位置">
- <el-row :gutter="10">
- <el-col :span="12">
- <span>X</span>
- <el-input-number
- v-model="editForm.qrCodePosX"
- :min="0"
- :precision="0"
- :step="1"
- controls-position="right"
- placeholder="X"
- />
- </el-col>
- <el-col :span="12">
- <span>Y</span>
- <el-input-number
- v-model="editForm.qrCodePosY"
- :min="0"
- :precision="0"
- :step="1"
- controls-position="right"
- placeholder="Y"
- />
- </el-col>
- </el-row>
- </el-form-item>
- <el-form-item label="二维码大小">
- <el-row :gutter="10">
- <el-col :span="12">
- <span>宽度</span>
- <el-input-number
- v-model="editForm.qrCodeWidth"
- :min="0"
- :precision="0"
- :step="1"
- controls-position="right"
- placeholder="宽度"
- />
- </el-col>
- <el-col :span="12">
- <span>高度</span>
- <el-input-number
- v-model="editForm.qrCodeHeight"
- :min="0"
- :precision="0"
- :step="1"
- controls-position="right"
- placeholder="高度"
- />
- </el-col>
- </el-row>
- </el-form-item>
- </el-form>
- </div>
- </div>
- <template #footer>
- <el-button @click="handleCancel">取消</el-button>
- <el-button type="primary" :loading="loading" @click="handleSave"
- >保存</el-button
- >
- </template>
- </el-dialog>
- </template>
- <script setup>
- import { ref, reactive } from 'vue';
- import { ElMessage } from 'element-plus';
- import ImageUpload from '@/components/ImageUpload/index.vue';
- import {
- getPosterTemplateInfo,
- addPosterTemplate,
- updatePosterTemplate
- } from '@/api/marketing/partner';
- const emit = defineEmits(['success']);
- // 表单实例
- const formRef = ref();
- // 编辑弹窗显示控制
- const visible = ref(false);
- // 加载状态
- const loading = ref(false);
- // 编辑表单数据
- const editForm = reactive({
- id: null,
- name: '',
- background: '',
- headImgPosX: '',
- headImgPosY: '',
- nickNamePosX: '',
- nickNamePosY: '',
- qrCodePosX: '',
- qrCodePosY: '',
- qrCodeWidth: '',
- qrCodeHeight: ''
- });
- // 表单验证规则
- const rules = {
- name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
- background: [
- { required: true, message: '请上传背景图片', trigger: 'change' }
- ]
- };
- // 打开弹窗
- const open = (row) => {
- visible.value = true;
- if (row?.id) {
- getDetail(row.id);
- } else {
- resetForm();
- }
- };
- // 获取详情
- const getDetail = async (id) => {
- try {
- const res = await getPosterTemplateInfo(id);
- if (res.data.code == 200) {
- Object.assign(editForm, res.data.data);
- }
- } catch (error) {
- ElMessage.error(error.message);
- }
- };
- // 重置表单
- const resetForm = () => {
- formRef.value?.resetFields();
- Object.assign(editForm, {
- id: null,
- name: '',
- background: '',
- headImgPosX: 0,
- headImgPosY: 0,
- nickNamePosX: 0,
- nickNamePosY: 0,
- qrCodePosX: 0,
- qrCodePosY: 0,
- qrCodeWidth: 0,
- qrCodeHeight: 0
- });
- };
- // 取消
- const handleCancel = () => {
- visible.value = false;
- };
- // 保存海报
- const handleSave = () => {
- formRef.value?.validate(async (valid) => {
- if (!valid) return;
- try {
- loading.value = true;
- const saveOrUpdate = editForm.id
- ? updatePosterTemplate
- : addPosterTemplate;
- await saveOrUpdate(editForm);
- ElMessage.success('保存成功');
- visible.value = false;
- emit('success');
- } catch (error) {
- ElMessage.error(error.message);
- } finally {
- loading.value = false;
- }
- });
- };
- defineExpose({ open });
- </script>
- <style lang="scss" scoped>
- .poster-edit-container {
- display: flex;
- gap: 20px;
- .mobile-preview {
- background: url('@/assets/mobile.png') no-repeat center center;
- background-size: 100% 100%;
- width: 445px;
- height: 750px;
- border-radius: 20px;
- overflow: hidden;
- flex-shrink: 0;
- .preview-content {
- padding: 16px;
- .preview-poster {
- position: relative;
- width: 250px;
- height: 445px;
- margin: 110px 82px;
- overflow: hidden;
- }
- }
- }
- .edit-form {
- flex: 1;
- padding: 20px;
- background: #fff;
- border-radius: 4px;
- }
- .el-col-12 {
- display: flex;
- align-items: center;
- justify-content: center;
- span {
- min-width: 40px;
- text-align: center;
- margin-right: 10px;
- }
- }
- }
- .upload-tip {
- font-size: 12px;
- color: #999;
- margin-top: 4px;
- }
- </style>
|