quanwei
2025-11-03 adf46e209a824f5d206fe549a252fd0184533b3a
shop_vue/src/views/plus/business/template/edit.vue
@@ -7,7 +7,7 @@
  <div class="user" v-loading="loading">
    <div class="common-form">名片模板编辑</div>
    <div class="poster-box d-s-s">
      <div class="left-box">
      <div class="left-box" style="width: auto;height: auto;min-height: auto;">
        <div v-if="form.backdrop" class="img"><img v-img-url="form.backdrop.src" /></div>
        <div class="userinfo">
          <!-- 头像 -->
@@ -18,7 +18,7 @@
               :style="'width:' + form.avatar.width + 'px;height:' + form.avatar.width + 'px;top:' + form.avatar.top + 'px;left:' + form.avatar.left + 'px;background-color:#f0f0f0;display:flex;align-items:center;justify-content:center;color:#999'">
            <span>头像</span>
          </div>
          <!-- Logo -->
          <div v-if="form.logo.display == 1"
               class="logo pa"
@@ -27,66 +27,66 @@
               :style="'width:' + form.logo.width + 'px;height:' + form.logo.height + 'px;top:' + form.logo.top + 'px;left:' + form.logo.left + 'px;'">
            <img v-img-url="form.logo.src" alt="" />
          </div>
          <!-- 姓名 -->
          <div class="name pa"
               v-drag="{type:'name',obj:this}"
               :style="'font-size:' + form.name.fontSize + 'px;color:' + form.name.color + ';top:' + form.name.top + 'px;left:' + form.name.left + 'px;'">
            这里是姓名
          </div>
          <!-- 手机 -->
          <div class="mobile pa"
               v-drag="{type:'mobile',obj:this}"
               :style="'font-size:' + form.mobile.fontSize + 'px;color:' + form.mobile.color + ';top:' + form.mobile.top + 'px;left:' + form.mobile.left + 'px;'">
            手机:134xxxxxxxx
          </div>
          <!-- 公司 -->
          <div v-for="(item, index) in form.unit" :key="'unit' + index"
               :class="'unit' + index + ' pa unit'"
               v-drag="{type:'unit', index:index, obj:this}"
               :style="'font-size:' + form.unit[index].fontSize + 'px;color:' + form.unit[index].color + ';top:' + form.unit[index].top + 'px;left:' + form.unit[index].left + 'px;'">
            这是公司{{index+1}}
            这是公司
          </div>
          <!-- 职位 -->
          <div v-for="(item, index) in form.duties" :key="'duties' + index"
               :class="'duties' + index + ' pa duties'"
               v-drag="{type:'duties', index:index, obj:this}"
               :style="'font-size:' + form.duties[index].fontSize + 'px;color:' + form.duties[index].color + ';top:' + form.duties[index].top + 'px;left:' + form.duties[index].left + 'px;'">
            这是职位{{index+1}}
            这是职位
          </div>
          <!-- 地址 -->
          <div v-for="(item, index) in form.address" :key="'address' + index"
               :class="'address' + index + ' pa address'"
               v-drag="{type:'address', index:index, obj:this}"
               :style="'font-size:' + form.address[index].fontSize + 'px;color:' + form.address[index].color + ';top:' + form.address[index].top + 'px;left:' + form.address[index].left + 'px;'">
            地址:广西壮族自治区南宁市江南区壮锦大道八桂绿城·龙湖御景-A栋-2单元{{index+1}}号
            地址:广西壮族自治区南宁市江南区壮锦大道八桂绿城·龙湖御景-A栋-2单元xxx号
          </div>
          <!-- 微信 -->
          <div class="wechat pa"
               v-drag="{type:'wechat',obj:this}"
               :style="'font-size:' + form.wechat.fontSize + 'px;color:' + form.wechat.color + ';top:' + form.wechat.top + 'px;left:' + form.wechat.left + 'px;'">
            微信:134xxxxxxxx
          </div>
          <!-- 邮箱 -->
          <div class="mailbox pa"
               v-drag="{type:'mailbox',obj:this}"
               :style="'font-size:' + form.mailbox.fontSize + 'px;color:' + form.mailbox.color + ';top:' + form.mailbox.top + 'px;left:' + form.mailbox.left + 'px;'">
            邮箱:134xxxxxxxx@.xxx.com
          </div>
          <!-- 电话 -->
          <div class="phone pa"
               v-drag="{type:'phone',obj:this}"
               :style="'font-size:' + form.phone.fontSize + 'px;color:' + form.phone.color + ';top:' + form.phone.top + 'px;left:' + form.phone.left + 'px;'">
            电话:xxx-xxx-xxx
          </div>
          <!-- 自定义图标 -->
          <div v-for="(item, index) in form.iconL" :key="'iconL' + index"
               :class="'iconL' + index + ' pa icon'"
@@ -96,15 +96,15 @@
          </div>
        </div>
      </div>
      <div class="right-box flex-1">
        <el-form size="small" ref="form" :model="form" label-width="150px">
          <!-- 背景图 -->
          <el-form-item label="海报背景图">
            <el-button type="primary" @click="openUpload(1)">上传图片</el-button>
            <div class="tips">尺寸建议:宽750像素 高大于(等于)1200像素</div>
            <div class="tips">尺寸建议:名片标准尺寸为1063x634像素</div>
          </el-form-item>
          <!-- 头像设置 -->
          <el-form-item label="是否显示头像">
            <el-radio v-model="form.avatar.display" label="1">显示</el-radio>
@@ -124,7 +124,7 @@
              <el-input v-model.number="form.avatar.top" min="0" type="number" class="max-w200" placeholder="上下位置"></el-input>
            </div>
          </el-form-item>
          <!-- Logo设置 -->
          <el-form-item label="是否显示Logo">
            <el-radio v-model="form.logo.display" label="1">显示</el-radio>
@@ -151,7 +151,7 @@
              <el-input v-model.number="form.logo.top" min="0" type="number" class="max-w200" placeholder="上下位置"></el-input>
            </div>
          </el-form-item>
          <!-- 姓名设置 -->
          <el-form-item label="姓名字体大小" prop="name.fontSize" :rules="[{ required: true, message: '请输入字体大小' }]">
            <el-input v-model.number="form.name.fontSize" min="12" type="number" class="max-w460"></el-input>
@@ -166,7 +166,7 @@
              <el-input v-model.number="form.name.top" min="0" type="number" class="max-w200" placeholder="上下位置"></el-input>
            </div>
          </el-form-item>
          <!-- 手机设置 -->
          <el-form-item label="手机字体大小" prop="mobile.fontSize" :rules="[{ required: true, message: '请输入字体大小' }]">
            <el-input v-model.number="form.mobile.fontSize" min="12" type="number" class="max-w460"></el-input>
@@ -181,9 +181,9 @@
              <el-input v-model.number="form.mobile.top" min="0" type="number" class="max-w200" placeholder="上下位置"></el-input>
            </div>
          </el-form-item>
          <!-- 图标数量设置 -->
          <el-form-item label="图标数量">
          <!--<el-form-item label="图标数量">
            <div class="d-s-r">
              <el-button type="text" @click="editIcon" :disabled="form.iconL.length <= 0">
                <i class="el-icon-minus"></i>
@@ -193,9 +193,9 @@
                <i class="el-icon-plus"></i>
              </el-button>
            </div>
          </el-form-item>
          <!-- 图标设置 -->
          </el-form-item>-->
          <!-- 图标设置
          <div v-for="(item, index) in form.iconL" :key="'icon_setting' + index" class="icon-setting">
            <el-form-item :label="'图标' + (index + 1)">
              <el-button type="primary" @click="openUpload(3, index)">上传图片</el-button>
@@ -214,9 +214,9 @@
                <el-input v-model.number="form.iconL[index].top" min="0" type="number" class="max-w200" placeholder="上下位置"></el-input>
              </div>
            </el-form-item>
          </div>
          <!-- 公司数量设置 -->
          </div>-->
          <!-- 公司数量设置
          <el-form-item label="公司数量">
            <div class="d-s-r">
              <el-button type="text" @click="editUnit" :disabled="form.unit.length <= 0">
@@ -227,17 +227,17 @@
                <i class="el-icon-plus"></i>
              </el-button>
            </div>
          </el-form-item>
          </el-form-item>-->
          <!-- 公司设置 -->
          <div v-for="(item, index) in form.unit" :key="'unit_setting' + index" class="unit-setting">
            <el-form-item :label="'公司' + (index + 1) + '字体大小'">
            <el-form-item :label="'公司字体大小'">
              <el-input v-model.number="form.unit[index].fontSize" min="12" type="number" class="max-w460"></el-input>
            </el-form-item>
            <el-form-item :label="'公司' + (index + 1) + '字体颜色'">
            <el-form-item :label="'公司字体颜色'">
              <el-color-picker v-model="form.unit[index].color"></el-color-picker>
            </el-form-item>
            <el-form-item :label="'公司' + (index + 1) + '位置'">
            <el-form-item :label="'公司位置'">
              <div class="d-s-r">
                <el-input v-model.number="form.unit[index].left" min="0" type="number" class="max-w200" placeholder="左右位置"></el-input>
                <span class="mr-10">x</span>
@@ -245,8 +245,8 @@
              </div>
            </el-form-item>
          </div>
          <!-- 职位数量设置 -->
          <!-- 职位数量设置
          <el-form-item label="职位数量">
            <div class="d-s-r">
              <el-button type="text" @click="editDuties" :disabled="form.duties.length <= 0">
@@ -257,17 +257,17 @@
                <i class="el-icon-plus"></i>
              </el-button>
            </div>
          </el-form-item>
          </el-form-item>-->
          <!-- 职位设置 -->
          <div v-for="(item, index) in form.duties" :key="'duties_setting' + index" class="duties-setting">
            <el-form-item :label="'职位' + (index + 1) + '字体大小'">
            <el-form-item :label="'职位字体大小'">
              <el-input v-model.number="form.duties[index].fontSize" min="12" type="number" class="max-w460"></el-input>
            </el-form-item>
            <el-form-item :label="'职位' + (index + 1) + '字体颜色'">
            <el-form-item :label="'职位字体颜色'">
              <el-color-picker v-model="form.duties[index].color"></el-color-picker>
            </el-form-item>
            <el-form-item :label="'职位' + (index + 1) + '位置'">
            <el-form-item :label="'职位位置'">
              <div class="d-s-r">
                <el-input v-model.number="form.duties[index].left" min="0" type="number" class="max-w200" placeholder="左右位置"></el-input>
                <span class="mr-10">x</span>
@@ -275,8 +275,8 @@
              </div>
            </el-form-item>
          </div>
          <!-- 地址数量设置 -->
          <!-- 地址数量设置
          <el-form-item label="地址数量">
            <div class="d-s-r">
              <el-button type="text" @click="editAddress" :disabled="form.address.length <= 0">
@@ -287,17 +287,17 @@
                <i class="el-icon-plus"></i>
              </el-button>
            </div>
          </el-form-item>
          </el-form-item>-->
          <!-- 地址设置 -->
          <div v-for="(item, index) in form.address" :key="'address_setting' + index" class="address-setting">
            <el-form-item :label="'地址' + (index + 1) + '字体大小'">
            <el-form-item :label="'地址字体大小'">
              <el-input v-model.number="form.address[index].fontSize" min="12" type="number" class="max-w460"></el-input>
            </el-form-item>
            <el-form-item :label="'地址' + (index + 1) + '字体颜色'">
            <el-form-item :label="'地址字体颜色'">
              <el-color-picker v-model="form.address[index].color"></el-color-picker>
            </el-form-item>
            <el-form-item :label="'地址' + (index + 1) + '位置'">
            <el-form-item :label="'地址位置'">
              <div class="d-s-r">
                <el-input v-model.number="form.address[index].left" min="0" type="number" class="max-w200" placeholder="左右位置"></el-input>
                <span class="mr-10">x</span>
@@ -305,7 +305,7 @@
              </div>
            </el-form-item>
          </div>
          <!-- 微信设置 -->
          <el-form-item label="微信字体大小">
            <el-input v-model.number="form.wechat.fontSize" min="12" type="number" class="max-w460"></el-input>
@@ -320,7 +320,7 @@
              <el-input v-model.number="form.wechat.top" min="0" type="number" class="max-w200" placeholder="上下位置"></el-input>
            </div>
          </el-form-item>
          <!-- 邮箱设置 -->
          <el-form-item label="邮箱字体大小">
            <el-input v-model.number="form.mailbox.fontSize" min="12" type="number" class="max-w460"></el-input>
@@ -335,7 +335,7 @@
              <el-input v-model.number="form.mailbox.top" min="0" type="number" class="max-w200" placeholder="上下位置"></el-input>
            </div>
          </el-form-item>
          <!-- 电话设置 -->
          <el-form-item label="电话字体大小">
            <el-input v-model.number="form.phone.fontSize" min="12" type="number" class="max-w460"></el-input>
@@ -350,7 +350,7 @@
              <el-input v-model.number="form.phone.top" min="0" type="number" class="max-w200" placeholder="上下位置"></el-input>
            </div>
          </el-form-item>
          <!-- 提交按钮 -->
          <div class="common-button-wrapper">
            <el-button @click="back">返回</el-button>
@@ -359,7 +359,7 @@
        </el-form>
      </div>
    </div>
    <!-- 上传图片组件 -->
    <Upload v-if="isupload" :isupload="isupload" :type="uploadType" :index="uploadIndex" @returnImgs="returnImgsFunc">上传图片</Upload>
  </div>
@@ -485,11 +485,11 @@
    drag: {
      inserted(el, binding) {
        const { type, obj } = binding.value;
        // 添加类型相关的类名,用于拖拽事件的绑定
        el.classList.add('drag');
        el.classList.add(type);
        // 避免指令和dragEventArray方法重复绑定拖拽事件
        // 实际的拖拽逻辑由dragEventArray方法处理
        el.style.position = 'absolute';
@@ -517,50 +517,50 @@
    dragEventArray(type) {
      // 使用类选择器获取对应的元素,更准确高效
      const elements = document.querySelectorAll(`.${type}`);
      elements.forEach((el, index) => {
        // 检查是否已经绑定过拖拽事件,避免重复绑定
        if (el.getAttribute('drag-handler') === 'true') return;
        el.setAttribute('drag-handler', 'true');
        // 为每个元素添加拖拽事件
        el.onmousedown = (event) => {
          event.preventDefault();
          // 计算鼠标按下位置与元素左上角的偏移
          let sentX = event.clientX - el.offsetLeft;
          let sentY = event.clientY - el.offsetTop;
          // 获取父容器的边界
          let parent = el.parentElement;
          let l = 0;
          let t = 0;
          let r = parent.offsetWidth - el.offsetWidth;
          let b = parent.offsetHeight - el.offsetHeight;
          document.onmousemove = (event) => {
            event.preventDefault();
            // 计算新位置
            let slideLeft = event.clientX - sentX;
            let slideTop = event.clientY - sentY;
            // 限制在父容器内
            slideLeft <= l && (slideLeft = l);
            slideLeft >= r && (slideLeft = r);
            slideTop <= t && (slideTop = t);
            slideTop >= b && (slideTop = b);
            // 更新位置
              if (Array.isArray(this.form[type]) && this.form[type][index]) {
                // 使用Vue.set确保响应式更新,这样右侧表单的位置输入框也能同步更新
                this.$set(this.form[type][index], 'left', slideLeft);
                this.$set(this.form[type][index], 'top', slideTop);
                // 直接更新DOM样式,确保视觉效果即时生效
                el.style.left = slideLeft + 'px';
                el.style.top = slideTop + 'px';
                // 强制Vue更新,确保表单输入框同步更新
                this.$forceUpdate();
              } else {
@@ -574,17 +574,17 @@
                this.$forceUpdate();
              }
          };
          document.onmouseup = () => {
            document.onmousemove = null;
            document.onmouseup = null;
          };
          return false;
        };
      });
    },
    // 加载数据
    loadData() {
      let self = this;
@@ -600,7 +600,7 @@
              if (!data.address) data.address = [];
              if (!data.iconL) data.iconL = [];
              self.form = data;
              // 数据加载完成后,重新初始化拖拽事件
              self.$nextTick(() => {
                ['unit', 'duties', 'address', 'iconL'].forEach(type => {
@@ -618,19 +618,19 @@
          console.error('加载数据失败', error);
        });
    },
    // 拖动处理
    dragDiv(x, y, type, index) {
      // 确保坐标值有效
      x = Math.max(0, x || 0);
      y = Math.max(0, y || 0);
      // 确保form对象存在
      if (!this.form) {
        console.warn('Form object not initialized');
        return;
      }
      switch (type) {
        case 'avatar':
          if (this.form.avatar) {
@@ -730,14 +730,14 @@
          console.warn('Unknown drag type:', type);
      }
    },
    // 打开上传
    openUpload(type, index) {
      this.uploadType = type;
      this.uploadIndex = index;
      this.isupload = true;
    },
    // 返回图片
    returnImgsFunc(e) {
      if (e && e.length > 0) {
@@ -759,7 +759,7 @@
      }
      this.isupload = false;
    },
    // 添加图标
    addIcon() {
      this.form.iconL.push({
@@ -774,14 +774,14 @@
        this.dragEventArray('iconL');
      });
    },
    // 减少图标
    editIcon() {
      if (this.form.iconL.length > 0) {
        this.form.iconL.pop();
      }
    },
    // 添加公司
    addUnit() {
      const index = this.form.unit.length;
@@ -793,20 +793,20 @@
        fontWeight: 100,
        type: 'text'
      });
      // 添加后重新初始化拖拽事件
      this.$nextTick(() => {
        this.dragEventArray('unit');
      });
    },
    // 减少公司
    editUnit() {
      if (this.form.unit.length > 0) {
        this.form.unit.pop();
      }
    },
    // 添加职位
    addDuties() {
      const index = this.form.duties.length;
@@ -818,20 +818,20 @@
        fontWeight: 400,
        type: 'text'
      });
      // 添加后重新初始化拖拽事件
      this.$nextTick(() => {
        this.dragEventArray('duties');
      });
    },
    // 减少职位
    editDuties() {
      if (this.form.duties.length > 0) {
        this.form.duties.pop();
      }
    },
    // 添加地址
    addAddress() {
      const index = this.form.address.length;
@@ -843,34 +843,34 @@
        fontWeight: 400,
        type: 'text'
      });
      // 添加后重新初始化拖拽事件
      this.$nextTick(() => {
        this.dragEventArray('address');
      });
    },
    // 减少地址
    editAddress() {
      if (this.form.address.length > 0) {
        this.form.address.pop();
      }
    },
    // 提交表单
    onSubmit() {
      let self = this;
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          // 确保必要字段存在
          if (!self.form.backdrop.src) {
            self.$message.error('请上传背景图');
            self.loading = false;
            return;
          }
          BusinessApi.templateEdit({
            template_id: self.template_id,
            template: self.form
@@ -881,7 +881,6 @@
                message: '保存成功',
                type: 'success'
              });
              self.$router.push('/plus/business/template/index');
            })
            .catch(error => {
              self.loading = false;
@@ -890,7 +889,7 @@
        }
      });
    },
    // 返回
    back() {
      this.$router.push('/plus/business/template/index');
@@ -1011,4 +1010,4 @@
  margin-bottom: 10px;
  border-radius: 4px;
}
</style>
</style>