zxl
2025-06-11 5500a2c52ff811c9041f6478d70ec07f788e5101
修改富文本,活动页面发布接口,新增接口,字段中文问题
3个文件已修改
1个文件已添加
511 ■■■■ 已修改文件
manager/src/components/editor/upload-image.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/libs/axios.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/views/activity/index.vue 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/views/customer/customer-tag/index.vue 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/components/editor/upload-image.vue
@@ -39,7 +39,7 @@
            ref="upload"
            :action="uploadFileUrl"
            :format="['jpg', 'jpeg', 'png']"
            :headers="{ ...accessToken }"
            :max-size="10240"
            :on-exceeded-size="handleMaxSize"
            :on-format-error="handleFormatError"
@@ -121,7 +121,8 @@
    // sku图片上传成功
    handleSuccessGoodsPicture(res, file) {
      if (file.response) {
        file.url = file.response.result;
        file.url = file.response.data.url;
        file.fileKey = file.response.data.fileKey
          this.images.push(file);
      }
    },
manager/src/libs/axios.js
@@ -16,7 +16,7 @@
    ? BASE.API_DEV.manager
    : BASE.API_PROD.manager) + BASE.PREFIX;
// 文件上传接口
export const uploadFile = commonUrl + "/common/common/upload/file";
export const uploadFile = commonUrl + "/common/lmk/file/upload";
const service = axios.create({
@@ -60,8 +60,8 @@
    }
    switch (data.code) {
      case 400:
        if (data.message !== null) {
          Message.error(data.message);
        if (data.msg !== null) {
          Message.error(data.msg);
        } else {
          Message.error("系统异常");
        }
@@ -72,8 +72,8 @@
        Cookies.set("userInfoManager", "");
        setStore("accessToken", "");
        if (router.history.current.name != "login") {
          if (data.message !== null) {
            Message.error(data.message);
          if (data.msg !== null) {
            Message.error(data.msg);
          } else {
            Message.error("未知错误,请重新登录");
          }
@@ -83,8 +83,8 @@
        break;
      case 500:
        // 系统异常
        if (data.message !== null) {
          Message.error(data.message);
        if (data.msg !== null) {
          Message.error(data.msg);
        } else {
          Message.error("系统异常");
        }
@@ -333,6 +333,15 @@
  });
};
export const uploadFileByLmk = (params) =>{
  return service({
    url: "/common/upload/file",
    method: "POST",
    headers:{'Content-Type': 'multipart/form-data'},
    data: params
  })
}
/**
 * 无需token验证的请求 避免旧token过期导致请求失败
 * @param {*} url
manager/src/views/activity/index.vue
@@ -34,7 +34,7 @@
              :value="item.value"
              :key="item.id"
            >
              {{ item.value }}
              {{ item.label }}
            </Option>
          </Select>
        </FormItem>
@@ -91,7 +91,7 @@
        <template slot-scope="{ row }" slot="url">
          <div class="media-container">
            <!-- 图片类型 -->
            <template v-if="row.coverType === '图片'">
            <template v-if="row.coverType === 'image'">
              <img
                :src="row.url"
                alt="活动封面"
@@ -100,7 +100,7 @@
              >
            </template>
            <!-- 视频类型 -->
            <template v-else-if="row.coverType === '视频'">
            <template v-else-if="row.coverType === 'video'">
              <video
                :src="row.url"
                class="video-player"
@@ -128,10 +128,10 @@
            <Button
              type="primary"
              size="small"
              @click="changeStatus(row, row.status === '已发布' ? '下架' : '发布')"
              @click="changeStatus(row, row.publish ? '下架' : '发布')"
              :loading="row.statusLoading"
            >
              {{ row.status === '已发布' ? '下架' : '发布' }}
              {{ row.publish  ? '下架' : '发布' }}
            </Button>
            <Button
              type="info"
@@ -188,7 +188,7 @@
              </FormItem>
            </Col>
            <Col span="12">
              <FormItem label="活动类型" prop="activityType">
              <FormItem label="活动类型" prop="activityType" :label-width="100">
                <Select
                  v-model="activityFrom.activityType"
                  placeholder="请选择活动类型"
@@ -199,7 +199,7 @@
                    :value="item.value"
                    :key="item.id"
                  >
                    {{ item.value }}
                    {{ item.label }}
                  </Option>
                </Select>
              </FormItem>
@@ -226,12 +226,11 @@
                ></DatePicker>
              </FormItem>
            </Col>
            <Col span="24">
              <FormItem label="封面类型" prop="coverType">
            <Col span="12">
              <FormItem label="封面类型" prop="coverType" :labelWidth="100">
                <Select
                  v-model="coverType"
                  placeholder="请选择封面类型"
                  clearable
                  @on-change="handleCoverTypeChange"
                >
                  <Option
@@ -265,15 +264,15 @@
                  accept="image/*,video/*"
                >
                  <Button icon="ios-cloud-upload-outline">上传封面文件</Button>
                  <div class="upload-tip">支持图片或视频文件,最大20MB</div>
                </Upload>
                <div v-if="file" class="upload-file-info">c
                <div v-if="file" class="upload-file-info">
                  已选文件: {{ file.name }}
                  <Button type="text" @click="handleRemove">删除</Button>
                </div>
              </FormItem>
            </Col>
            <!-- 这两个表单项在同一Row内,会显示在同一行 -->
            <Col span="12">
              <FormItem label="人数限制" prop="limitUserNum">
                <InputNumber
@@ -293,18 +292,8 @@
              </FormItem>
            </Col>
            <Col span="24">
              <Form :model="videoDownForm" :rules="videoDownRule" ref="videoDownForm">
<!--                <FormItem label="下架原因:" :labelWidth="100" prop="activityContent">-->
<!--                  <editor ref="editor" @input="getReason" />-->
<!--                </FormItem>-->
              </Form>
              <FormItem label="活动内容" prop="activityContent">
                <Input
                  v-model="activityFrom.activityContent"
                  type="textarea"
                  :rows="4"
                  placeholder="请输入活动详细内容"
                />
              <FormItem label="活动内容:" prop="activityContent">
                <editor ref="editor" @input="getReason" />
              </FormItem>
            </Col>
          </Row>
@@ -372,27 +361,6 @@
  components: {Editor},
  data() {
    return {
      videoDownForm :{
        id: '',
        reason: ''
      },
      videoDownRule: {
        reason: [
          {
            require: true,
            message: '请输入活动内容',
            trigger: 'blur',
            validator: (rule, value, callback) => {
              if (value === null || value === '') {
                callback(new Error('请输入活动内容'));
              } else {
                callback();
              }
            }
          }
        ]
      },
      loading: false,
      membersLoading: false,
      submitLoading: false,
@@ -415,8 +383,8 @@
      // 活动类型选项
      typeSelect: [
        { id: 1, value: '线上' },
        { id: 2, value: '线下' }
        { id: 1, value: 'online',label:'线上' },
        { id: 2, value: 'offline',label:'线下' }
      ],
      // 封面类型选项
@@ -444,7 +412,7 @@
        endTime: '',
        recommend: false,
        limitUserNum: 0,
        activityLocation: ''
        activityLocation: '',
      },
      // 表单验证规则
@@ -466,6 +434,9 @@
        ],
        cover: [
          { required: true, message: '请输入封面内容', trigger: 'blur' }
        ],
        coverType: [
          { required: true, message: '请选择封面类型', trigger: 'blur' }
        ],
        limitUserNum: [
          { required: true, type: 'number', message: '请输入人数限制', trigger: 'blur' },
@@ -497,7 +468,11 @@
          title: '活动类型',
          key: 'activityType',
          width: 100,
          align: 'center'
          align: 'center',
          render: (h, params) => {
            return h('Tag', {
            }, params.row.activityType === 'online' ? '线上' : '线下')
          }
        },
        {
          title: '推荐',
@@ -513,27 +488,37 @@
          }
        },
        {
          title: '状态',
          key: 'status',
          title: '发布',
          key: 'publish',
          width: 100,
          align: 'center',
          render: (h, params) => {
            return h('Tag', {
              props: {
                color: params.row.status === '已发布' ? 'blue' : 'orange'
                color: params.row.publish ? 'green' : 'default'
              }
            }, params.row.status)
            }, params.row.publish ? '已发布' : '未发布')
          }
        },
        {
          title: '报名时间段',
          key: 'reportTimeRange',
          width: 300,
          title: '状态',
          key: 'status',
          width: 100,
          align: 'center',
          render: (h, params) => {
            return h('div', [
              h('div', `开始: ${this.formatDate(params.row.reportStartTime)}`),
              h('div', `结束: ${this.formatDate(params.row.reportEndTime)}`)
            ])
            const status = params.row.status;
            const statusMap = {
              'noStart': { text: '未开始', color: 'default' },
              'report': { text: '报名中', color: 'green' },
              'inProgress':{ text:'进行中',color:'cyan'},
              'end': { text: '已结束', color: 'red' }
            };
            const currentStatus = statusMap[status] || { text: status, color: 'default' };
            return h('Tag', {
              props: {
                color: currentStatus.color
              }
            }, currentStatus.text);
          }
        },
        {
@@ -558,7 +543,16 @@
          title: '封面类型',
          key: 'coverType',
          width: 100,
          align: 'center'
          align: 'center',
          render: (h, params) => {
            const typeMap = {
              text: '文本',
              video: '视频',
              image: '图片'
            };
            const text = typeMap[params.row.coverType] || params.row.coverType;
            return h('span', text);
          }
        },
        {
          title: '人数限制',
@@ -653,8 +647,7 @@
  methods: {
    // 获取富文本编辑器的内容
    getReason(content) {
      this.videoDownForm.reason = content
      console.log(content)
      this.activityFrom.activityContent = content
    },
    // 初始化数据
    init() {
@@ -674,8 +667,6 @@
            statusLoading: false
          }))
          this.total = res.total
        } else {
          this.$Message.error(res.msg || '获取活动列表失败')
        }
      }).catch(() => {
        this.loading = false
@@ -724,7 +715,7 @@
    openAdd() {
      this.modelTitle = '新增活动'
      this.modelShow = true
      this.coverType = ''
      this.coverType = '输入文字封面'
      this.file = null
      this.$refs.form.resetFields()
      this.activityFrom.id = ''
@@ -736,7 +727,6 @@
      this.modelShow = true
      this.$nextTick(() => {
        this.$refs.form.resetFields()
        // 填充表单数据
        this.activityFrom = {
          id: row.id,
@@ -762,9 +752,9 @@
          limitUserNum: row.limitUserNum,
          activityLocation: row.activityLocation
        }
        this.$refs.editor.setContent(this.activityFrom.activityLocation)
        // 设置封面类型
        this.coverType = row.coverType === '文字' ? '输入文字封面' : '选择文件封面'
        this.coverType = row.coverType === 'text' ? '输入文字封面' : '选择文件封面'
      })
    },
@@ -773,11 +763,16 @@
      this.modelShow = false
      this.file = null
      this.submitLoading = false
      this.handleRemove();
      this.$refs.form.resetFields()
    },
    // 保存或更新活动
    saveOrUpdate() {
      // 设置封面类型
      this.activityFrom.coverType = this.coverType === '输入文字封面' ? '文字' :
        this.file ? this.getFileCategory(this.file.type) :
          this.activityFrom.coverType
      this.$refs.form.validate(valid => {
        if (valid) {
          this.submitLoading = true
@@ -793,11 +788,6 @@
            this.activityFrom.endTime =  this.formatDate(this.activityFrom.time[1], 'YYYY-MM-DD HH:mm:ss')
          }
          // 设置封面类型
          this.activityFrom.coverType = this.coverType === '输入文字封面' ? '文字' :
            this.file ? this.getFileCategory(this.file.type) :
              this.activityFrom.coverType
          const api = this.activityFrom.id ? editActivity : addActivity
          api(this.activityFrom).then(res => {
            this.submitLoading = false
@@ -805,8 +795,6 @@
              this.$Message.success(res.msg)
              this.modelClose()
              this.getActivityList()
            } else {
              this.$Message.error(res.msg || '操作失败')
            }
          }).catch(() => {
            this.submitLoading = false
@@ -825,8 +813,6 @@
            if (res.code === 200) {
              this.$Message.success(res.msg)
              this.getActivityList()
            } else {
              this.$Message.error(res.msg || '删除失败')
            }
          })
        }
@@ -871,8 +857,6 @@
        if (res.code === 200) {
          this.$Message.success(res.msg)
          row.recommend = recommend
        } else {
          this.$Message.error(res.msg || '操作失败')
        }
      }).catch(() => {
        row.recommendLoading = false
@@ -882,18 +866,16 @@
    // 改变活动状态
    changeStatus(row, action) {
      row.statusLoading = true
      const status = action === '发布' ? '已发布' : '已下架'
      const publish = action === '发布'
      activityChangeStatus({
        id: row.id,
        status: status
        publish: publish
      }).then(res => {
        row.statusLoading = false
        if (res.code === 200) {
          this.$Message.success(res.msg)
          row.status = status
        } else {
          this.$Message.error(res.msg || '操作失败')
          row.publish = publish
        }
      }).catch(() => {
        row.statusLoading = false
@@ -917,8 +899,6 @@
        if (res.code === 200) {
          this.membersList = res.data
          this.memberTotal = res.total
        } else {
          this.$Message.error(res.msg || '获取报名人员失败')
        }
      }).catch(() => {
        this.membersLoading = false
@@ -986,8 +966,6 @@
        if (res.code === 200) {
          this.activityFrom.cover = res.data.fileKey
          this.$Message.success('上传成功')
        } else {
          this.$Message.error(res.msg || '上传失败')
        }
      }).catch(() => {
        this.submitLoading = false
@@ -996,24 +974,18 @@
    // 删除文件
    handleRemove() {
      //点击关闭窗口时确保文件已被清除
      if(this.file === null){
        return;
      }
      if (!this.activityFrom.cover) {
        this.file = null
        return
      }
      this.$Modal.confirm({
        title: '确认删除',
        content: '确定要删除已上传的文件吗?',
        onOk: () => {
          delByKey(this.activityFrom.cover).then(res => {
            if (res.code === 200) {
              this.$Message.success(res.msg)
              this.file = null
              this.activityFrom.cover = ''
            } else {
              this.$Message.error(res.msg || '删除失败')
            }
          })
      delByKey(this.activityFrom.cover).then(res => {
        if (res.code === 200) {
          this.file = null
          this.activityFrom.cover = ''
        }
      })
    },
@@ -1027,14 +999,14 @@
    // 获取文件分类
    getFileCategory(mimeType) {
      const typeMap = {
        'image': '图片',
        'video': '视频',
        'audio': '音频',
        'application': '文档'
        'image': 'image',
        'video': 'video',
        'audio': 'audio',
        'application': 'application'
      }
      const typePrefix = mimeType.split('/')[0]
      return typeMap[typePrefix] || '未知'
      return typeMap[typePrefix] || 'unknown'
    },
    // 格式化日期
manager/src/views/customer/customer-tag/index.vue
New file
@@ -0,0 +1,295 @@
<template>
  <div>
    <card>
      <Form
        ref="searchForm"
        @keydown.enter.native="handleSearch"
        :model="searchForm"
        inline
        :label-width="70"
        class="search-form"
      >
        <Form-item label="标签名称" prop="tagName">
          <Input
            type="text"
            v-model="searchForm.tagName"
            clearable
            @on-clear="handleSearch"
            @on-change="handleSearch"
            style="width: 160px"
          />
        </Form-item>
        <Form-item label="标签来源" prop="createType">
          <Select
            v-model="searchForm.createType"
            clearable
            @on-clear="handleSearch"
            @on-change="handleSearch"
            style="width: 160px"
          >
            <Option value="SYSTEM">系统创建</Option>
            <Option value="USER">用户创建</Option>
          </Select>
        </Form-item>
        <Button
          @click="handleSearch"
          type="primary"
          icon="ios-search"
          class="search-btn"
        >搜索</Button
        >
      </Form>
      <Row class="operation padding-row">
        <Button @click="openAdd" type="info">添加</Button>
        <Button @click="delBatch" type="error">批量删除</Button>
      </Row>
      <Table
        :loading="loading"
        border
        :columns="columns"
        :data="tagList"
        ref="table"
        sortable="custom"
        @on-sort-change="changeSort"
        @on-selection-change="showSelect"
      >
        <template slot-scope="{ row, index }" slot="action">
          <Button type="info" size="small" style="margin-right: 5px" @click="openEdit(row)">编辑标签</Button>
          <Button type="error" size="small" style="margin-right: 5px" @click="del(row)">删除标签</Button>
        </template>
      </Table>
      <Row type="flex" justify="end" class="mt_10">
        <Page
          :current="searchForm.pageNumber"
          :total="total"
          :page-size="searchForm.pageSize"
          @on-change="changePage"
          @on-page-size-change="changePageSize"
          :page-size-opts="[10, 20, 50]"
          size="small"
          show-total
          show-elevator
          show-sizer
        ></Page>
      </Row>
      <Modal
        v-model="modelShow"
        :title="modelTitle"
      >
        <Form ref="form" :model="form" :label-width="70" :rules="rules">
          <FormItem label="标签名称" prop="tagName">
            <Input v-model="form.tagName" autocomplete="off"/>
          </FormItem>
        </Form>
        <div slot="footer">
          <Button type="text" @click="modelClose">取消</Button>
          <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">提交</Button>
        </div>
      </Modal>
    </card>
  </div>
</template>
<script>
import JsonExcel from "vue-json-excel";
import {getPageTagList,addCustomerTag,editTag,} from "@/api/customer";
export default {
  name:"customer-tag",
  components:{
    "download-excel": JsonExcel,
  },
  data(){
    return{
      loading:false,
      columns:[
        {
          type: 'selection',
          width: 60,
          align: 'center'
        },
        {
          title:'标签名称',
          key: 'tagName',
          minWidth: 60,
          tooltip: true,
        },
        {
          title: '操作',
          key: 'action',
          slot: 'action',
          minWidth: 150,
          align: 'center'
        }
      ],
      total:0,
      tagList:[],
      searchForm: {
        // 搜索框初始化对象
        pageNumber: 1, // 当前页数
        pageSize: 10, // 页面大小
        tagName: '', // 标签名称
        createType: '', // 创建方式
      },
      // 对话框标题
      modelTitle:'',
      modelShow:false,
      submitLoading:false,
      // 表单
      form: {
        id: '',
        tagName: '',
        createType: 'SYSTEM'
      },
      rules: {
        tagName: [
          {required: true, message: "标签名称不能为空", trigger: "blur"}
        ],
      },
      //多选
      selectCount: 0, // 已选数量
      selectList: [], // 已选数据列表
    }
  },
  mounted(){
    this.init();
  },
  methods:{
    init(){
      this.getTagList()
    },
    getTagList(){
      this.loading = true;
      getPageTagList(this.searchForm).then((res) => {
        this.loading = false;
        if (res.code === 200) {
          this.tagList = res.data;
          this.total = res.total;
        }
      });
      this.loading = false;
    },
    handleSearch(){
      this.searchForm.pageNumber = 1;
      this.searchForm.pageSize = 10;
      this.getTagList();
    },
    openAdd(){
      this.modelTitle = "新增标签"
      this.modelShow = true
    },
    saveOrUpdate() {
      this.$refs.form.validate(valid => {
        if (valid) {
          this.submitLoading = true
          if (this.form.id) {
            // 修改
            editTag(this.form).then(res => {
              if (res.code === 200) {
                this.$Message.success("修改成功");
                this.modelClose()
                this.getTagList()
              }
            })
          } else {
            // 新增
            addCustomerTag(this.form).then(res => {
              if (res.code === 200) {
                this.$Message.success("添加成功");
                this.modelClose()
                this.getTagList()
              }
            })
          }
        }
      });
    },
    // 关闭弹窗
    modelClose() {
      this.submitLoading = false
      this.modelShow = false
    },
    delBatch(){
      if (this.selectCount <= 0) {
        this.$Message.warning("您还未选择要删除的数据");
        return;
      }
      this.$Modal.confirm({
        title: "确认删除",
        content: "您确认要删除所选的 " + this.selectCount + " 条数据?",
        loading: true,
        onOk: () => {
        }
      });
    },
    openEdit(row){
    },
    del(row){
    },
    // 分页 改变页码
    changePage(v) {
      this.searchForm.pageNumber = v;
      this.getTagList();
    },
    // 分页 改变页数
    changePageSize(v) {
      this.searchForm.pageNumber = 1;
      this.searchForm.pageSize = v;
      this.getTagList();
    },
    changeSort(){
    },
    showSelect(){
      this.selectList = e.map(d => d.id);
      this.selectCount = e.length;
    },
  }
}
</script>
<style lang="scss" scoped>
.export {
  margin: 10px 20px 10px 0;
}
.export-excel-wrapper {
  display: inline;
}
.order-tab {
  width: 950px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: #f0f0f0;
  padding: 0 10px;
  margin-bottom: 10px;
  div {
    text-align: center;
    padding: 4px 12px;
    border-radius: 4px;
    cursor: pointer;
  }
  .current {
    background-color: #ffffff;
  }
}
</style>