Merge remote-tracking branch 'origin/dev' into dev
| | |
| | | }) |
| | | } |
| | | |
| | | export const getCustomerInfo= (params) =>{ |
| | | return service({ |
| | | url: '/customerManager/'+ params, |
| | | method: 'GET' |
| | | }) |
| | | } |
| New file |
| | |
| | | import service from "../libs/axios"; |
| | | |
| | | export const getNews = (params) =>{ |
| | | return service({ |
| | | url: "/news/page", |
| | | method: "GET", |
| | | params: params |
| | | }) |
| | | } |
| | | |
| | | export const addNews = (params) =>{ |
| | | return service({ |
| | | url: "/news", |
| | | method: "POST", |
| | | data: params |
| | | }) |
| | | } |
| | | |
| | | export const editNews = (params) =>{ |
| | | return service({ |
| | | url: "/news", |
| | | method: "PUT", |
| | | data: params |
| | | }) |
| | | } |
| | | |
| | | export const publish = (param) =>{ |
| | | return service({ |
| | | url: "/news/publish/"+ param, |
| | | method: "PUT", |
| | | }) |
| | | } |
| | | |
| | | export const delById = (param) =>{ |
| | | return service({ |
| | | url: "/news/"+ param, |
| | | method: "DELETE", |
| | | }) |
| | | } |
| | |
| | | export const getLogisticsChecked = () => { |
| | | return getRequest(`/other/logistics/getChecked`) |
| | | } |
| | | //查询包裹列表 |
| | | export const getPackage = (orderSn) => { |
| | | return getRequest(`/order/order/getPackage/${orderSn}`); |
| | | } |
| | | |
| | | //查询物流 |
| | | export const getTraces = (sn, params) => { |
| New file |
| | |
| | | import service from "@/libs/axios"; |
| | | |
| | | // 获取标签分类列表 |
| | | export const getTagTypeList = (params) => { |
| | | return service({ |
| | | url: "/lmk/tag-type/list", |
| | | method: "GET", |
| | | params: params |
| | | }) |
| | | } |
| | | |
| | | export const getTagKeyTypeList = () => { |
| | | return service({ |
| | | url: "/lmk/tag-type/key/list", |
| | | method: "GET" |
| | | }) |
| | | } |
| | | |
| | | |
| | | |
| | | // 通过id删除标签分类 |
| | | export const deleteTagTypeById = (params) => { |
| | | return service({ |
| | | url: "/lmk/tag-type/" + params, |
| | | method: "DELETE" |
| | | }) |
| | | } |
| | | |
| | | |
| | | // 修改标签分类 |
| | | export const updateTagType = (params) => { |
| | | return service({ |
| | | url: "/lmk/tag-type/", |
| | | method: "PUT", |
| | | data: params |
| | | }) |
| | | } |
| | | |
| | | // 添加标签分类 |
| | | export const saveTagType = (params) => { |
| | | return service({ |
| | | url: "/lmk/tag-type/", |
| | | method: "POST", |
| | | data: params |
| | | }) |
| | | } |
| | | |
| | | |
| New file |
| | |
| | | import service from "@/libs/axios"; |
| | | |
| | | // 获取标签分页 |
| | | export const getTags = (data) => { |
| | | return service({ |
| | | url: "/lmk/tag/page", |
| | | method: "GET", |
| | | params: data |
| | | }) |
| | | } |
| | | |
| | | // 获取标签列表 |
| | | export const getTagList = () => { |
| | | return service({ |
| | | url: "/lmk/tag/list", |
| | | method: "GET" |
| | | }) |
| | | } |
| | | |
| | | |
| | | // 通过id删除标签 |
| | | export const deleteTagById = (params) => { |
| | | return service({ |
| | | url: "/lmk/tag/" + params, |
| | | method: "DELETE" |
| | | }) |
| | | } |
| | | |
| | | |
| | | // 修改标签 |
| | | export const editTag = (params) => { |
| | | return service({ |
| | | url: "/lmk/tag/", |
| | | method: "PUT", |
| | | data: params |
| | | }) |
| | | } |
| | | |
| | | // 添加标签 |
| | | export const addTag = (params) => { |
| | | return service({ |
| | | url: "/lmk/tag/", |
| | | method: "POST", |
| | | data: params |
| | | }) |
| | | } |
| | | |
| | |
| | | <Button |
| | | type="info" |
| | | size="small" |
| | | @click="detail(row)" |
| | | >详情</Button> |
| | | <Button |
| | | type="info" |
| | | size="small" |
| | | @click="openEdit(row)" |
| | | >编辑</Button> |
| | | <Button |
| | |
| | | </Row> |
| | | </Modal> |
| | | |
| | | <Modal |
| | | v-model="infoModelShow" |
| | | :title="modelTitle" |
| | | @on-cancel="infoModelClose" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <div class="detail-container"> |
| | | <Row :gutter="16"> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>活动名称:</label> |
| | | <span>{{ activityInfo.activityName || '-' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>活动类型:</label> |
| | | <span>{{activityInfo.activityType === 'online' ? '线上':'线下'}}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>报名时间段:</label> |
| | | <span>{{ activityInfo.reportStartTime }} - {{ activityInfo.reportEndTime }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>活动时间段:</label> |
| | | <span>{{ activityInfo.startTime }} - {{ activityInfo.endTime }}</span> |
| | | </div> |
| | | </Col> |
| | | |
| | | <Col span="24" v-if="coverType === '输入文字封面'"> |
| | | <div class="detail-item"> |
| | | <label>封面文字:</label> |
| | | <span>{{ activityInfo.cover || '-' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="24" v-if="coverType === '选择文件封面'"> |
| | | <div class="detail-item"> |
| | | <label>上传封面:</label> |
| | | <span>{{ activityInfo.cover }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>人数限制:</label> |
| | | <span>{{ activityInfo.limitUserNum || '无限制' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>活动地点:</label> |
| | | <span>{{ activityInfo.activityLocation || '-' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="24"> |
| | | <div class="detail-item"> |
| | | <label>活动内容:</label> |
| | | <div |
| | | class="activity-content" |
| | | v-html="activityInfo.activityContent || '无内容'" |
| | | ></div> |
| | | </div> |
| | | </Col> |
| | | </Row> |
| | | </div> |
| | | |
| | | <div slot="footer"> |
| | | <Button @click="infoModelClose">关闭</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | |
| | | <!-- 图片预览模态框 --> |
| | | <Modal v-model="previewVisible" title="图片预览" footer-hide> |
| | | <img :src="previewImageUrl" style="width: 100%"> |
| | |
| | | components: {Editor}, |
| | | data() { |
| | | return { |
| | | infoModelShow:false, |
| | | |
| | | loading: false, |
| | | membersLoading: false, |
| | | submitLoading: false, |
| | |
| | | |
| | | // 活动表单 |
| | | activityFrom: { |
| | | id: '', |
| | | activityName: '', |
| | | activityType: '', |
| | | reportTime: [], |
| | | time: [], |
| | | activityContent: '', |
| | | cover: '', |
| | | coverType: '', |
| | | status: '', |
| | | reportStartTime: '', |
| | | reportEndTime: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | recommend: false, |
| | | limitUserNum: 0, |
| | | activityLocation: '', |
| | | }, |
| | | activityInfo: { |
| | | id: '', |
| | | activityName: '', |
| | | activityType: '', |
| | |
| | | this.init() |
| | | }, |
| | | methods: { |
| | | detail(row){ |
| | | this.modelTitle = '活动详情' |
| | | this.infoModelShow = true |
| | | this.activityInfo = row |
| | | }, |
| | | // 获取富文本编辑器的内容 |
| | | getReason(content) { |
| | | this.activityFrom.activityContent = content |
| | |
| | | this.coverType = row.coverType === 'text' ? '输入文字封面' : '选择文件封面' |
| | | }) |
| | | }, |
| | | |
| | | infoModelClose(){ |
| | | this.infoModelShow = false |
| | | }, |
| | | // 关闭模态框 |
| | | modelClose() { |
| | | this.modelShow = false |
| | |
| | | margin-top: 4px; |
| | | } |
| | | } |
| | | .detail-container { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .detail-item { |
| | | margin-bottom: 18px; |
| | | line-height: 1.5; |
| | | |
| | | label { |
| | | display: inline-block; |
| | | width: 100px; |
| | | color: #666; |
| | | font-weight: bold; |
| | | vertical-align: top; |
| | | } |
| | | |
| | | span { |
| | | display: inline-block; |
| | | width: calc(100% - 110px); |
| | | } |
| | | } |
| | | |
| | | .activity-content { |
| | | border: 1px solid #dcdee2; |
| | | border-radius: 4px; |
| | | padding: 12px; |
| | | min-height: 100px; |
| | | margin-top: 8px; |
| | | } |
| | | </style> |
| | |
| | | @on-selection-change="showSelect" |
| | | > |
| | | <template slot-scope="{ row, index }" slot="action"> |
| | | <Button type="info" size="small" style="margin-right: 5px" @click="openInfo(row)">查看详情</Button> |
| | | <Button type="info" size="small" style="margin-right: 5px" @click="openEdit(row)">编辑标签</Button> |
| | | <Button type="error" size="small" style="margin-right: 5px" @click="joinBlack(row)">加入黑名单</Button> |
| | | </template> |
| | |
| | | ></Page> |
| | | </Row> |
| | | |
| | | <Modal |
| | | v-model="showCustomerInfo" |
| | | :title="modelTitle" |
| | | width="700" |
| | | :mask-closable="false" |
| | | > |
| | | <div class="customer-detail"> |
| | | <div class="avatar-section"> |
| | | <Avatar :src="customerInfo.face" size="large" /> |
| | | <div class="basic-info"> |
| | | <h3>{{ customerInfo.nickName || '微信用户' }}</h3> |
| | | <p>ID: {{ customerInfo.id }}</p> |
| | | <p>用户名: {{ customerInfo.username }}</p> |
| | | </div> |
| | | </div> |
| | | |
| | | <Divider /> |
| | | |
| | | <div class="detail-grid"> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">性别:</span> |
| | | <span class="detail-value">{{ customerInfo.sex === 0 ? "女" : "男"}}</span> |
| | | </div> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">地区:</span> |
| | | <span class="detail-value">{{ customerInfo.region || '未设置' }}</span> |
| | | </div> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">手机号:</span> |
| | | <span class="detail-value">{{ customerInfo.mobile || '未绑定' }}</span> |
| | | </div> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">当前积分:</span> |
| | | <span class="detail-value">{{ customerInfo.point }}</span> |
| | | </div> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">总积分:</span> |
| | | <span class="detail-value">{{ customerInfo.totalPoint }}</span> |
| | | </div> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">账号状态:</span> |
| | | <span class="detail-value"> |
| | | <Tag :color="customerInfo.disabled ? 'error' : 'success'"> |
| | | {{ customerInfo.disabled ? '已禁用' : '正常' }} |
| | | </Tag> |
| | | </span> |
| | | </div> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">是否关联店铺:</span> |
| | | <span class="detail-value">{{ customerInfo.haveStore ? '是' : '否' }}</span> |
| | | </div> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">注册时间:</span> |
| | | <span class="detail-value">{{ customerInfo.createTime }}</span> |
| | | </div> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">最后登录时间:</span> |
| | | <span class="detail-value">{{ customerInfo.lastLoginDate }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div v-if="customerInfo.customerTagList && customerInfo.customerTagList.length > 0" class="tags-section"> |
| | | <h4>用户标签</h4> |
| | | <div> |
| | | <Tag v-for="tag in customerInfo.customerTagList" :key="tag" color="default" style="margin-right: 8px;"> |
| | | {{ tag }} |
| | | </Tag> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div slot="footer"> |
| | | <Button type="primary" @click="showCustomerInfo = false">关闭</Button> |
| | | </div> |
| | | </Modal> |
| | | <!-- 标签弹窗--> |
| | | <Modal |
| | | v-model="showCustomerTag" |
| | | :title="modelTitle" |
| | |
| | | |
| | | <script> |
| | | import JsonExcel from "vue-json-excel"; |
| | | import {getCustomerList,addCustomerTag,saveCustomerTagById,getTagList,getStoreSelectOptions} from "@/api/customer"; |
| | | import {getCustomerList,addCustomerTag,saveCustomerTagById,getTagList,getStoreSelectOptions,getCustomerInfo} from "@/api/customer"; |
| | | import {addCustomerBlackByPC} from "@/api/customer-black.js" |
| | | |
| | | export default { |
| | |
| | | }, |
| | | data(){ |
| | | return{ |
| | | customerInfo: { |
| | | birthday: null, |
| | | blackId: null, |
| | | clientEnum: null, |
| | | createTime: "", |
| | | customerTagList: [], |
| | | disabled: true, |
| | | experience: null, |
| | | face: "", |
| | | gradeId: null, |
| | | haveStore: false, |
| | | id: "", |
| | | lastLoginDate: "", |
| | | mobile: null, |
| | | nickName: "", |
| | | openId: null, |
| | | point: 10, |
| | | region: "", |
| | | regionId: "", |
| | | sex: 0, |
| | | storeId: null, |
| | | totalPoint: 0, |
| | | username: "" |
| | | }, |
| | | loading: false, // 表单加载状态 |
| | | //查询客户列表请求参数 |
| | | searchForm:{ |
| | |
| | | selectCount: 0, // 已选数量 |
| | | selectList: [], // 已选数据列表 |
| | | |
| | | //客户详情对话框--- |
| | | showCustomerInfo:false, |
| | | //客户标签对话框--- |
| | | |
| | | showCustomerTag:false, |
| | | submitLoading:false, |
| | | selectLoading:false, |
| | |
| | | this.selectList = e.map(d => d.id); |
| | | this.selectCount = e.length; |
| | | }, |
| | | //查看详情 |
| | | openInfo(row){ |
| | | this.showCustomerInfo = true; |
| | | this.modelTitle = "用户详情" |
| | | getCustomerInfo(row.id).then(res =>{ |
| | | if(res.code === 200){ |
| | | this.customerInfo = { |
| | | birthday: res.data.birthday || null, |
| | | blackId: res.data.blackId || null, |
| | | clientEnum: res.data.clientEnum || null, |
| | | createTime: res.data.createTime || '', |
| | | customerTagList: res.data.customerTagList || [], |
| | | disabled: res.data.disabled || false, |
| | | experience: res.data.experience || null, |
| | | face: res.data.face || '默认头像URL', |
| | | gradeId: res.data.gradeId || null, |
| | | haveStore: res.data.haveStore || false, |
| | | id: res.data.id || '', |
| | | lastLoginDate: res.data.lastLoginDate || '', |
| | | mobile: res.data.mobile || null, |
| | | nickName: res.data.nickName || '微信用户', |
| | | openId: res.data.openId || null, |
| | | point: res.data.point || 0, |
| | | region: res.data.region || '', |
| | | regionId: res.data.regionId || '', |
| | | sex: res.data.sex || 0, |
| | | storeId: res.data.storeId || null, |
| | | totalPoint: res.data.totalPoint || 0, |
| | | username: res.data.username || '' |
| | | }; |
| | | } |
| | | }) |
| | | }, |
| | | // 编辑标签 |
| | | openEdit(row){ |
| | | this.showCustomerTag = true |
| | |
| | | |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .customer-detail { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .avatar-section { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .basic-info { |
| | | margin-left: 16px; |
| | | } |
| | | |
| | | .basic-info h3 { |
| | | margin: 0 0 8px 0; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .basic-info p { |
| | | margin: 6px 0; |
| | | color: #808695; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .tags-section { |
| | | margin-top: 16px; |
| | | padding-top: 16px; |
| | | } |
| | | |
| | | .tags-section h4 { |
| | | margin-bottom: 12px; |
| | | color: #17233d; |
| | | } |
| | | .export { |
| | | margin: 10px 20px 10px 0; |
| | | } |
| | |
| | | <template slot="goodsSlot" slot-scope="{ row }"> |
| | | <div style="margin: 5px 0px; height: 80px; display: flex"> |
| | | <div style=""> |
| | | <img |
| | | <img v-if="row.original" |
| | | :src="row.original" |
| | | style="height: 60px; margin-top: 1px; width: 60px" |
| | | /> |
| | | <video v-else |
| | | :src="row.goodsVideo" style="height: 60px; margin-top: 1px; width: 60px" |
| | | /> |
| | | </div> |
| | | |
| | |
| | | |
| | | <script> |
| | | import { getGoodsListData, upGoods, lowGoods } from "@/api/goods"; |
| | | import {getSts} from '@/api/file' |
| | | import vueQr from "vue-qr"; |
| | | export default { |
| | | components: { |
| | |
| | | this.loading = false; |
| | | if (res.success) { |
| | | this.data = res.result.records; |
| | | getSts().then(res => { |
| | | const endpoint = res.data.endpoint |
| | | this.data.forEach(item => { |
| | | if (item.goodsVideo != null && item.goodsVideo.indexOf('http')===-1) { |
| | | item.goodsVideo = endpoint + '/' + item.goodsVideo; |
| | | } |
| | | if (item.original !=null && item.original.indexOf('http') ===-1) { |
| | | item.original = endpoint + '/' + item.original; |
| | | } |
| | | }) |
| | | }) |
| | | |
| | | this.total = res.result.total; |
| | | } |
| | | }); |
| | |
| | | <!-- 商品栏目格式化 --> |
| | | <template slot="goodsSlot" slot-scope="scope"> |
| | | <div style="margin-top: 5px; height: 80px; display: flex"> |
| | | <div style=""> |
| | | <img |
| | | <div style="" > |
| | | <img v-if="scope.row.original" |
| | | :src="scope.row.original" |
| | | style="height: 60px; margin-top: 3px; width: 60px" |
| | | /> |
| | | <video v-else :src="scope.row.goodsVideo" style="height: 60px; margin-top: 3px; width: 60px" |
| | | /> |
| | | </div> |
| | | |
| | | <div style="margin-left: 13px"> |
| | |
| | | </template> |
| | | <script> |
| | | import { getGoodsDetail } from "@/api/goods"; |
| | | import {getSts} from '@/api/file' |
| | | export default { |
| | | name: "goodsDetail", |
| | | data() { |
| | |
| | | initGoods(id) { |
| | | getGoodsDetail(id).then((res) => { |
| | | this.goods = res.result; |
| | | if (this.goods.goodsVideo != null && this.goods.goodsVideo !== '') { |
| | | getSts().then(res => { |
| | | console.log('--------------->',this.goods.goodsVideo.indexOf('http')!== -1) |
| | | if (this.goods.goodsVideo !== null && this.goods.goodsVideo.indexOf('http')=== -1) { |
| | | this.goods.goodsVideo = res.data.endpoint+'/'+this.goods.goodsVideo; |
| | | } |
| | | }) |
| | | } |
| | | if (this.goods.goodsGalleryList != null && this.goods.goodsGalleryList.length > 0) { |
| | | getSts().then(res => { |
| | | this.goods.goodsGalleryList = this.goods.goodsGalleryList.map((item) => { |
| | | if (item !== null&&item.indexOf('http')===-1) { |
| | | return res.data.endpoint+'/'+item; |
| | | }else { |
| | | return item; |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | let that = this; |
| | | res.result.skuList.forEach(function (sku, index, array) { |
| | | that.skuData.push({ |
| | |
| | | <FormItem label="视频"> |
| | | <video style="width: 150px;height: 150px" |
| | | controls |
| | | @loadedmetadata="getVideoDuration" |
| | | :poster="uploadVideoForm.showCoverUrl" |
| | | :autoplay="false" |
| | | id="remoteVideo" :src="uploadVideoForm.showVideoUrl" |
| | |
| | | this.auditingLoading = false |
| | | }) |
| | | }, |
| | | getVideoDuration(e){ |
| | | const duration = this.$refs.healthVideoInfo.duration; |
| | | this.uploadVideoForm.videoDuration = Math.floor(duration); |
| | | }, |
| | | // 打开编辑弹窗 |
| | | deleteHealthVideo(row) { |
| | | console.log('删除测试', row) |
| | |
| | | <FormItem label="视频"> |
| | | <video style="width: 150px;height: 150px" |
| | | controls |
| | | @loadedmetadata="getVideoDuration" |
| | | :poster="uploadVideoForm.showCoverUrl" |
| | | :autoplay="false" |
| | | id="remoteVideo" :src="uploadVideoForm.showVideoUrl" |
| | |
| | | this.$set(this.uploadVideoForm, 'temp', new Date().getTime()); |
| | | console.log(this.uploadVideoForm) |
| | | }, |
| | | getVideoDuration(e){ |
| | | const duration = this.$refs.healthVideoInfo.duration; |
| | | this.uploadVideoForm.videoDuration = Math.floor(duration); |
| | | }, |
| | | // 视频上架 |
| | | videoUp(row) { |
| | | this.$Modal.confirm({ |
| New file |
| | |
| | | <template> |
| | | <div class="news-management"> |
| | | <Card> |
| | | <!-- 搜索表单 --> |
| | | <Form |
| | | ref="searchForm" |
| | | @keydown.enter.native="handleSearch" |
| | | :model="searchForm" |
| | | inline |
| | | :label-width="80" |
| | | class="search-form" |
| | | > |
| | | <FormItem label="标题" prop="title"> |
| | | <Input |
| | | type="text" |
| | | v-model="searchForm.title" |
| | | placeholder="请输入标题名称" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | style="width: 180px" |
| | | /> |
| | | </FormItem> |
| | | <FormItem label="是否发布" prop="publish"> |
| | | <Select |
| | | v-model="searchForm.publish" |
| | | placeholder="请选择" |
| | | style="width: 180px" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | > |
| | | <Option |
| | | v-for="item in typeSelect" |
| | | :value="item.value" |
| | | :key="item.id" |
| | | > |
| | | {{ item.label }} |
| | | </Option> |
| | | </Select> |
| | | </FormItem> |
| | | <Button |
| | | @click="handleSearch" |
| | | type="primary" |
| | | icon="ios-search" |
| | | class="search-btn" |
| | | >搜索</Button> |
| | | <Button |
| | | @click="resetSearch" |
| | | icon="md-refresh" |
| | | style="margin-left: 8px" |
| | | >重置</Button> |
| | | </Form> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <Row class="operation"> |
| | | <Button @click="openAdd" type="primary" icon="md-add">新增活动</Button> |
| | | <Button @click="delBatch" type="error" icon="md-trash" :disabled="selectCount === 0">批量删除</Button> |
| | | </Row> |
| | | |
| | | <!-- 活动表格 --> |
| | | <Table |
| | | :loading="loading" |
| | | border |
| | | :columns="columns" |
| | | :data="newsList" |
| | | ref="table" |
| | | @on-selection-change="showSelect" |
| | | class="news-table" |
| | | > |
| | | <!-- 封面展示插槽 --> |
| | | <!-- 操作按钮插槽 --> |
| | | <template slot-scope="{ row }" slot="action"> |
| | | <div class="action-btns"> |
| | | <Button |
| | | type="primary" |
| | | size="small" |
| | | @click="changeStatus(row, row.publish ? '下架' : '发布')" |
| | | :loading="row.statusLoading" |
| | | > |
| | | {{ row.publish ? '下架' : '发布' }} |
| | | </Button> |
| | | <Button |
| | | type="info" |
| | | size="small" |
| | | @click="detail(row)" |
| | | >详情</Button> |
| | | <Button |
| | | type="info" |
| | | size="small" |
| | | @click="openEdit(row)" |
| | | >编辑</Button> |
| | | <Button |
| | | type="error" |
| | | size="small" |
| | | @click="delById(row)" |
| | | >删除</Button> |
| | | </div> |
| | | </template> |
| | | </Table> |
| | | |
| | | <!-- 分页 --> |
| | | <Row type="flex" justify="end" class="page-footer"> |
| | | <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" |
| | | @on-cancel="modelClose" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <Form ref="form" :model="newsForm" :label-width="100" :rules="rules"> |
| | | <Row :gutter="16"> |
| | | <Col span="12"> |
| | | <FormItem label="标题" prop="title"> |
| | | <Input |
| | | v-model="newsForm.title" |
| | | placeholder="请输入标题名称" |
| | | clearable |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24"> |
| | | <FormItem label="新闻内容:" prop="content"> |
| | | <editor ref="editor" @input="getReason" /> |
| | | </FormItem> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | |
| | | <div slot="footer"> |
| | | <Button @click="modelClose">取消</Button> |
| | | <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">提交</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | |
| | | <Modal |
| | | v-model="infoModelShow" |
| | | :title="modelTitle" |
| | | @on-cancel="infoModelClose" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <div class="detail-container"> |
| | | <Row :gutter="16"> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>标题:</label> |
| | | <span>{{ newsInfo.title || '-' }}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="12"> |
| | | <div class="detail-item"> |
| | | <label>是否发布:</label> |
| | | <span>{{newsInfo.publish ? '已发布':'未发布'}}</span> |
| | | </div> |
| | | </Col> |
| | | |
| | | <Col span="12"> |
| | | <div class="detail-item" v-if="newsInfo.publish"> |
| | | <label>发布时间:</label> |
| | | <span>{{ newsInfo.publishDate}}</span> |
| | | </div> |
| | | </Col> |
| | | <Col span="24"> |
| | | <div class="detail-item"> |
| | | <label>新闻内容:</label> |
| | | <div |
| | | class="news-content" |
| | | v-html="newsInfo.content || '无内容'" |
| | | ></div> |
| | | </div> |
| | | </Col> |
| | | </Row> |
| | | </div> |
| | | |
| | | <div slot="footer"> |
| | | <Button @click="infoModelClose">关闭</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | |
| | | <!-- 图片预览模态框 --> |
| | | <Modal v-model="previewVisible" title="图片预览" footer-hide> |
| | | <img :src="previewImageUrl" style="width: 100%"> |
| | | </Modal> |
| | | </Card> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import Editor from '@/components/editor/index.vue' |
| | | import { getNews,editNews,addNews,publish,delById } from '@/api/news.js' |
| | | export default { |
| | | name: "newsManagement", |
| | | components: {Editor}, |
| | | data(){ |
| | | return{ |
| | | // 图片预览 |
| | | previewVisible: false, |
| | | previewImageUrl: '', |
| | | |
| | | modelShow:false, |
| | | modelTitle:'', |
| | | submitLoading:false, |
| | | infoModelShow:false, |
| | | //表头 |
| | | columns: [ |
| | | { |
| | | type: 'selection', |
| | | width: 60, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: '标题', |
| | | key: 'title', |
| | | minWidth: 120, |
| | | tooltip: true |
| | | }, |
| | | { |
| | | title: '发布', |
| | | key: 'publish', |
| | | width: 100, |
| | | align: 'center', |
| | | render: (h, params) => { |
| | | return h('Tag', { |
| | | props: { |
| | | color: params.row.publish ? 'green' : 'default' |
| | | } |
| | | }, params.row.publish ? '已发布' : '未发布') |
| | | } |
| | | }, |
| | | { |
| | | title: '发布时间', |
| | | key: 'publishDate', |
| | | width: 300, |
| | | align: 'center', |
| | | render: (h, { row }) => { |
| | | // 如果 publishDate 为 null 或 undefined,显示 "未发布" |
| | | if (row.publishDate == null) { |
| | | return h('span', { style: { color: '#999' } }, '暂无'); |
| | | } |
| | | // 否则正常显示日期 |
| | | return h('span', row.publishDate); |
| | | }, |
| | | }, |
| | | { |
| | | title: '操作', |
| | | slot: 'action', |
| | | width: 280, |
| | | align: 'center', |
| | | fixed: 'right' |
| | | } |
| | | ], |
| | | |
| | | newsList:[], |
| | | total:0, |
| | | newsForm:{ |
| | | id:'', |
| | | title:'', |
| | | content:'', |
| | | publish:0, |
| | | }, |
| | | newsInfo:{ |
| | | title:'', |
| | | publish:false, |
| | | publishDate:'', |
| | | content:'' |
| | | }, |
| | | rules: { |
| | | title: [ |
| | | { required: true, message: '请输入标题', trigger: 'blur' }, |
| | | { max: 50, message: '长度不能超过50个字符', trigger: 'blur' } |
| | | ], |
| | | publish: [ |
| | | { required: true, message: '请选择是否发布', trigger: 'blur' }, |
| | | ], |
| | | content: [ |
| | | { required: true, message: '请输入新闻内容', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | selectList:[], |
| | | selectCount:0, |
| | | |
| | | loading:false, |
| | | |
| | | searchForm: { |
| | | title: '', |
| | | publish: 0, |
| | | pageNumber: 1, |
| | | pageSize: 10 |
| | | }, |
| | | typeSelect:[ |
| | | { |
| | | id:1, |
| | | label:'未发布', |
| | | value:0 |
| | | }, |
| | | { |
| | | id:2, |
| | | label:'已发布', |
| | | value:1 |
| | | } |
| | | |
| | | ] |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getNewsList(); |
| | | }, |
| | | methods:{ |
| | | getNewsList(){ |
| | | this.loading = true |
| | | getNews(this.searchForm).then(res =>{ |
| | | this.loading = false |
| | | if (res.code === 200) { |
| | | // 为每一行添加loading状态 |
| | | this.newsList = res.data.map(item => ({ |
| | | ...item, |
| | | })) |
| | | this.total = res.total |
| | | } |
| | | }).catch(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | getReason(content) { |
| | | this.newsForm.content = content |
| | | }, |
| | | saveOrUpdate(){ |
| | | this.$refs.form.validate(valid => { |
| | | if (valid) { |
| | | this.submitLoading = true |
| | | const submitData = { |
| | | ...this.newsForm, |
| | | publish: this.newsForm.publish !== 0, // true → 1, false → 0 |
| | | }; |
| | | if (this.newsForm.id){ |
| | | editNews(submitData).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.modelClose() |
| | | this.getNewsList() |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | }else { |
| | | addNews(submitData).then(res => { |
| | | this.submitLoading = false |
| | | if (res.code === 200) { |
| | | this.$Message.success(res.msg) |
| | | this.modelClose() |
| | | this.getNewsList() |
| | | } |
| | | }).catch(() => { |
| | | this.submitLoading = false |
| | | }) |
| | | } |
| | | |
| | | } |
| | | }) |
| | | }, |
| | | infoModelClose(){ |
| | | this.infoModelShow = false; |
| | | }, |
| | | modelClose(){ |
| | | this.modelShow = false; |
| | | }, |
| | | changePage(page) { |
| | | this.searchForm.pageNumber = page |
| | | this.getNewsList() |
| | | }, |
| | | // 改变每页条数 |
| | | changePageSize(pageSize) { |
| | | this.searchForm.pageNumber = 1 |
| | | this.searchForm.pageSize = pageSize |
| | | this.getNewsList() |
| | | }, |
| | | |
| | | delById(row){ |
| | | delById(row.id).then(res =>{ |
| | | if (res.code === 200){ |
| | | this.$Message.success(res.msg); |
| | | this.getNewsList(); |
| | | } |
| | | |
| | | }) |
| | | }, |
| | | openEdit(row){ |
| | | this.modelTitle = '修改新闻'; |
| | | this.modelShow = true; |
| | | this.$refs.form.resetFields(); |
| | | this.newsForm.title = row.title; |
| | | this.newsForm.content = row.content; |
| | | this.newsForm.id = row.id; |
| | | this.$refs.editor.setContent(this.newsForm.content) |
| | | }, |
| | | openAdd(){ |
| | | this.modelTitle = '新增新闻'; |
| | | this.modelShow = true; |
| | | this.$refs.form.resetFields() |
| | | this.newsForm.id = ''; |
| | | |
| | | }, |
| | | detail(row){ |
| | | this.modelTitle = '活动详情' |
| | | this.infoModelShow = true |
| | | this.newsInfo = row |
| | | }, |
| | | changeStatus(row,action){ |
| | | row.statusLoading = true; |
| | | |
| | | publish(row.id).then(res =>{ |
| | | row.statusLoading = false |
| | | if (res.code === 200){ |
| | | this.$Message.success(res.msg); |
| | | this.getNewsList(); |
| | | } |
| | | }).catch(() => { |
| | | row.statusLoading = false |
| | | }) |
| | | }, |
| | | // 表格选择变化 |
| | | showSelect(selection) { |
| | | this.selectList = selection.map(item => item.id) |
| | | this.selectCount = selection.length |
| | | }, |
| | | |
| | | delBatch(){ |
| | | |
| | | }, |
| | | handleSearch(type, value){ |
| | | this.searchForm.pageNumber = 1 |
| | | this.getNewsList() |
| | | }, |
| | | resetSearch(){ |
| | | this.$refs.searchForm.resetFields() |
| | | this.searchForm.pageNumber = 1 |
| | | this.getNewsList() |
| | | }, |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .activity-management { |
| | | .search-form { |
| | | padding: 16px; |
| | | background: #f8f8f9; |
| | | border-radius: 4px; |
| | | margin-bottom: 16px; |
| | | |
| | | .ivu-form-item { |
| | | margin-bottom: 16px; |
| | | margin-right: 16px; |
| | | } |
| | | |
| | | .search-btn { |
| | | margin-left: 8px; |
| | | } |
| | | } |
| | | } |
| | | .detail-container { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .detail-item { |
| | | margin-bottom: 18px; |
| | | line-height: 1.5; |
| | | |
| | | label { |
| | | display: inline-block; |
| | | width: 100px; |
| | | color: #666; |
| | | font-weight: bold; |
| | | vertical-align: top; |
| | | } |
| | | |
| | | span { |
| | | display: inline-block; |
| | | width: calc(100% - 110px); |
| | | } |
| | | } |
| | | |
| | | .news-content { |
| | | border: 1px solid #dcdee2; |
| | | border-radius: 4px; |
| | | padding: 12px; |
| | | min-height: 100px; |
| | | margin-top: 8px; |
| | | } |
| | | .news-table { |
| | | .media-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 100px; |
| | | |
| | | .thumbnail { |
| | | max-width: 100%; |
| | | max-height: 100%; |
| | | object-fit: contain; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | |
| | | &:hover { |
| | | transform: scale(1.05); |
| | | box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .action-btns { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | justify-content: center; |
| | | |
| | | .ivu-btn { |
| | | margin: 4px; |
| | | font-size: 12px; |
| | | padding: 2px 6px; |
| | | min-width: 60px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <Button v-if="allowOperation.editConsignee" @click="editAddress" type="primary" ghost>修改收货地址</Button> |
| | | <Button v-if="allowOperation.cancel" @click="orderCancel" type="warning" ghost>订单取消</Button> |
| | | <Button v-if="orderInfo.order.orderStatus === 'UNPAID'" @click="confirmPrice" type="primary">收款</Button> |
| | | <Button v-if="allowOperation.showLogistics || orderPackage.length > 0" @click="checkLogistics" type="primary">查看物流</Button> |
| | | <Button @click="orderLog" type="info" ghost>订单日志</Button> |
| | | <Button @click="printOrder" type="primary" ghost style="float:right;" |
| | | v-if="$route.query.orderType != 'VIRTUAL'">打印发货单</Button> |
| | |
| | | <Button type="primary" @click="modifyPriceSubmit">调整</Button> |
| | | </div> |
| | | </Modal> |
| | | <!-- 查询物流 --> |
| | | <Modal v-model="logisticsModal" width="40"> |
| | | <p slot="header"> |
| | | <span>查询物流</span> |
| | | </p> |
| | | <div class="layui-layer-wrap"> |
| | | <dl> |
| | | <dt>订单号:</dt> |
| | | <dd> |
| | | <div class="text-box">{{ sn }}</div> |
| | | </dd> |
| | | </dl> |
| | | </div> |
| | | <div v-if="packageTraceList.length > 0" v-for="(packageItem, packageIndex) in packageTraceList" :key="packageIndex"> |
| | | <div class="layui-layer-wrap"> |
| | | <dl> |
| | | <dt>物流公司:</dt> |
| | | <dd><div class="text-box">{{ packageItem.logisticsName }}</div></dd> |
| | | </dl> |
| | | <dl> |
| | | <dt>快递单号:</dt> |
| | | <dd><div nctype="ordersSn" class="text-box">{{ packageItem.logisticsNo }}</div></dd> |
| | | </dl> |
| | | <div class="div-express-log"> |
| | | <ul class="express-log express-log-name"> |
| | | <li v-for="(item, index) in packageItem.orderPackageItemList" :key="index"> |
| | | <span class="time" style="width: 50%;"><span>商品名称:</span><span>{{ item.goodsName }}</span></span> |
| | | <span class="time" style="width: 30%;"><span>发货时间:</span><span>{{ item.logisticsTime }}</span></span> |
| | | <span class="time" style="width: 20%;"><span>发货数量:</span><span>{{ item.deliverNumber }}</span></span> |
| | | </li> |
| | | </ul> |
| | | </div> |
| | | <div class="div-express-log"> |
| | | <ul class="express-log" v-if="packageItem.traces && packageItem.traces.traces"> |
| | | <li v-for="(item, index) in packageItem.traces.traces" :key="index"> |
| | | <span class="time">{{ item.AcceptTime || item.acceptTime }}</span> |
| | | <span class="detail">{{ item.AcceptStation || item.remark }}</span> |
| | | </li> |
| | | </ul> |
| | | <ul class="express-log" v-else><li>暂无物流信息</li></ul> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-if = "packageTraceList.length == 0 && logisticsInfo"> |
| | | <div class="layui-layer-wrap"> |
| | | <dl> |
| | | <dt>物流公司:</dt> |
| | | <dd><div class="text-box">{{ logisticsInfo.shipper }}</div></dd> |
| | | </dl> |
| | | <dl> |
| | | <dt>快递单号:</dt> |
| | | <dd><div nctype="ordersSn" class="text-box">{{ logisticsInfo.logisticCode }}</div></dd> |
| | | </dl> |
| | | <div class="div-express-log"> |
| | | <ul class="express-log" v-if="logisticsInfo && logisticsInfo.traces"> |
| | | <li v-for="(item, index) in logisticsInfo.traces" :key="index"> |
| | | <span class="time">{{ item.AcceptTime }}</span> |
| | | <span class="detail">{{ item.AcceptStation }}</span> |
| | | </li> |
| | | </ul> |
| | | <ul class="express-log" v-else><li>暂无物流信息</li></ul> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div slot="footer" style="text-align: right"> |
| | | <Button @click="logisticsModal = false">取消</Button> |
| | | </div> |
| | | </Modal> |
| | | <!-- 订单取消模态框 --> |
| | | <Modal v-model="orderCancelModal" width="530"> |
| | | <p slot="header"> |
| | |
| | | orderLogModal: false, //弹出调整价格框 |
| | | checkedLogistics: [], //选中的物流公司集合 |
| | | allowOperation: {}, //订单可才做选项 |
| | | logisticsModal: false, //弹出查询物流框 |
| | | packageTraceList: [], |
| | | orderPackage: [], |
| | | logisticsInfo: { |
| | | shipper: "", |
| | | }, //物流信息 |
| | | sn: "", //订单编号 |
| | | orderInfo: { |
| | | order: { |
| | |
| | | gotoHomes () { |
| | | return false |
| | | }, |
| | | |
| | | getOrderPackage() { |
| | | API_Order.getPackage(this.sn).then(res => { |
| | | if (res.success) { |
| | | this.orderPackage = res.result; |
| | | console.log('this.orderPackage',this.orderPackage); |
| | | } |
| | | }) |
| | | }, |
| | | //查询物流 |
| | | checkLogistics () { |
| | | this.logisticsModal = true; |
| | | if (this.orderPackage.length > 0) { |
| | | this.logisticsList(); |
| | | } else { |
| | | this.logistics(); |
| | | } |
| | | }, |
| | | logisticsList () { |
| | | this.logisticsModal = true; |
| | | API_Order.getPackage(this.sn).then((res) => { |
| | | if (res.success && res.result != null) { |
| | | this.packageTraceList = res.result; |
| | | } |
| | | }); |
| | | }, |
| | | logistics () { |
| | | this.logisticsModal = true; |
| | | API_Order.getTraces(this.sn).then((res) => { |
| | | if (res.success && res.result != null) { |
| | | this.logisticsInfo = res.result; |
| | | } |
| | | }); |
| | | }, |
| | | //确认收款 |
| | | confirmPrice () { |
| | | this.$Modal.confirm({ |
| | |
| | | mounted () { |
| | | this.sn = this.$route.query.sn; |
| | | this.getDataList(); |
| | | this.getOrderPackage(); |
| | | }, |
| | | }; |
| | | </script> |
| | |
| | | } |
| | | } |
| | | } |
| | | .div-express-log { |
| | | max-height: 300px; |
| | | border: solid 1px #e7e7e7; |
| | | background: #fafafa; |
| | | overflow-y: auto; |
| | | overflow-x: auto; |
| | | } |
| | | .layui-layer-wrap { |
| | | dl { |
| | | border-top: solid 1px #f5f5f5; |
| | | margin-top: -1px; |
| | | overflow: hidden; |
| | | |
| | | dt { |
| | | font-size: 14px; |
| | | line-height: 28px; |
| | | display: inline-block; |
| | | padding: 8px 1% 8px 0; |
| | | color: #999; |
| | | } |
| | | |
| | | dd { |
| | | font-size: 14px; |
| | | line-height: 28px; |
| | | display: inline-block; |
| | | padding: 8px 0 8px 8px; |
| | | border-left: solid 1px #f5f5f5; |
| | | |
| | | .text-box { |
| | | line-height: 40px; |
| | | color: #333; |
| | | word-break: break-all; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .express-log { |
| | | /*margin: 5px -10px 5px 5px;*/ |
| | | padding: 10px; |
| | | list-style-type: none; |
| | | |
| | | .time { |
| | | width: 30%; |
| | | display: inline-block; |
| | | float: left; |
| | | } |
| | | |
| | | .detail { |
| | | width: 60%; |
| | | margin-left: 30px; |
| | | display: inline-block; |
| | | } |
| | | |
| | | li { |
| | | line-height: 30px; |
| | | } |
| | | } |
| | | |
| | | .express-log-name { |
| | | li { |
| | | display: flex; |
| | | span { |
| | | display: flex; |
| | | } |
| | | } |
| | | } |
| | | .f14 { |
| | | font-size: 14px; |
| | | color: #333; |
| New file |
| | |
| | | <template> |
| | | <div> |
| | | <Card> |
| | | <div class="operation mb_10"> |
| | | <Button @click="addParent" type="primary" icon="md-add">添加一级分类</Button> |
| | | </div> |
| | | <tree-table ref="treeTable" size="default" :loading="loading" :data="tableData" :columns="columns" |
| | | :border="true" :show-index="false" :is-fold="true" :expand-type="false" primary-key="id"> |
| | | <template slot="action" slot-scope="scope"> |
| | | <Button type="info" @click="edit(scope.row)" size="small" style="margin-right: 5px">编辑 |
| | | </Button> |
| | | |
| | | <Button type="error" @click="remove(scope.row)" size="small" style="margin-right: 5px">删除 |
| | | </Button> |
| | | <Button v-show="scope.row.level != 1" type="success" @click="addChildren(scope.row)" size="small" |
| | | style="margin-right: 5px">添加子分类 |
| | | </Button> |
| | | </template> |
| | | </tree-table> |
| | | </Card> |
| | | <Modal :title="modalTitle" v-model="modalVisible" :mask-closable="false" :width="500"> |
| | | <Form ref="formAdd" :model="formAdd" :label-width="100" :rules="formValidate"> |
| | | <div v-if="showParent"> |
| | | <FormItem label="上级分类" prop="parentId"> |
| | | {{ parentTitle }} |
| | | <Input v-model="formAdd.parentId" clearable style="width: 100%; display: none" /> |
| | | </FormItem> |
| | | </div> |
| | | <FormItem label="分类名称" prop="tagTypeName"> |
| | | <Input v-model="formAdd.tagTypeName" clearable style="width: 100%" /> |
| | | </FormItem> |
| | | <FormItem label="分类标识" prop="typeKey"> |
| | | |
| | | <Select v-model="formAdd.typeKey" :disabled="formAdd.parentId!==0" placeholder="请选择分类标识" filterable :popper-append-to-body="false" |
| | | popper-class="spec-values-popper" style="width: 100%; text-align: left; margin-right: 10px"> |
| | | <Option v-for="item in typeKeyList" :value="item.value" :label="item.value" :key="item.value"> |
| | | </Option> |
| | | </Select> |
| | | </FormItem> |
| | | <FormItem label="排序值" prop="sortNum"> |
| | | <InputNumber v-model="formAdd.sortNum"></InputNumber> |
| | | </FormItem> |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="modalVisible = false">取消</Button> |
| | | <Button type="primary" :loading="submitLoading" @click="Submit">提交</Button> |
| | | </div> |
| | | </Modal> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import { |
| | | saveTagType, |
| | | getTagTypeList , |
| | | deleteTagTypeById, |
| | | updateTagType,getTagKeyTypeList |
| | | } from "@/api/tag-type"; |
| | | import TreeTable from "@/components/tree-table/Table/Table"; |
| | | import uploadPicInput from "@/components/lili/upload-pic-input"; |
| | | import { regular } from "@/utils"; |
| | | export default { |
| | | name: "lili-components", |
| | | components: { |
| | | TreeTable, |
| | | uploadPicInput, |
| | | }, |
| | | data() { |
| | | return { |
| | | submitLoading: false, |
| | | loading: false, // 加载状态 |
| | | expandLevel: 1, // 展开的层级 |
| | | modalType: 0, // 添加或编辑标识 |
| | | modalVisible: false, // 添加或编辑显示 |
| | | modalTitle: "", // 添加或编辑标题 |
| | | showParent: false, // 是否展示上级菜单 |
| | | parentTitle: "", // 父级菜单名称 |
| | | formAdd: { |
| | | // 添加或编辑表单对象初始化数据 |
| | | parentId: "", |
| | | sortNum: 1, |
| | | level: 0, |
| | | tagTypeName: "", |
| | | typeKey:'' |
| | | }, |
| | | // 表单验证规则 |
| | | formValidate: { |
| | | tagTypeName: [regular.REQUIRED], |
| | | typeKey: [regular.REQUIRED], |
| | | sortNum: [regular.REQUIRED, regular.INTEGER], |
| | | }, |
| | | columns: [ |
| | | { |
| | | title: "分类名称", |
| | | key: "tagTypeName", |
| | | witt: "100px", |
| | | }, |
| | | { |
| | | title: "分类标识", |
| | | key: "typeKey", |
| | | witt: "100px", |
| | | }, |
| | | { |
| | | title: "排序", |
| | | key: "sortNum", |
| | | width: "100px", |
| | | }, |
| | | { |
| | | title: "操作", |
| | | key: "action", |
| | | align: "center", |
| | | headerAlign: "center", |
| | | width: "400px", |
| | | type: "template", |
| | | template: "action", |
| | | }, |
| | | ], |
| | | typeKeyList: [], |
| | | tableData: [], // 表格数据 |
| | | }; |
| | | }, |
| | | methods: { |
| | | // 初始化数据 |
| | | init() { |
| | | this.getAllList(); |
| | | this.getKeyTypeList(); |
| | | }, |
| | | getKeyTypeList() { |
| | | getTagKeyTypeList().then((res) => { |
| | | this.typeKeyList = res.data |
| | | }) |
| | | }, |
| | | // 添加子分类 |
| | | addChildren(v) { |
| | | this.modalType = 0; |
| | | this.modalTitle = "添加子分类"; |
| | | this.formAdd.tagTypeName = ""; |
| | | this.parentTitle = v.tagTypeName; |
| | | this.formAdd.typeKey = v.typeKey; |
| | | this.typeKeyEdit = false |
| | | this.formAdd.level = eval(v.level + "+1"); |
| | | this.showParent = true; |
| | | delete this.formAdd.id; |
| | | this.formAdd.parentId = v.id; |
| | | this.modalVisible = true; |
| | | }, |
| | | // 编辑分类 |
| | | edit(v) { |
| | | this.modalType = 1; |
| | | this.modalTitle = "编辑"; |
| | | this.formAdd.id = v.id; |
| | | this.formAdd.tagTypeName = v.tagTypeName; |
| | | this.formAdd.level = v.level; |
| | | this.formAdd.parentId = v.parentId; |
| | | this.formAdd.sortNum = v.sortNum; |
| | | this.showParent = false; |
| | | this.modalVisible = true; |
| | | }, |
| | | // 添加一级分类 |
| | | addParent() { |
| | | this.modalType = 0; |
| | | this.modalTitle = "添加一级分类"; |
| | | this.parentTitle = "顶级分类"; |
| | | this.showParent = true; |
| | | this.$refs.formAdd.resetFields(); |
| | | delete this.formAdd.id; |
| | | this.formAdd.parentId = 0; |
| | | this.modalVisible = true; |
| | | }, |
| | | // 提交 |
| | | Submit() { |
| | | this.$refs.formAdd.validate((valid) => { |
| | | if (valid) { |
| | | this.submitLoading = true; |
| | | if (this.modalType === 0) { |
| | | // 添加 避免编辑后传入id等数据 记得删除 |
| | | delete this.formAdd.id; |
| | | saveTagType(this.formAdd).then((res) => { |
| | | this.submitLoading = false; |
| | | if (res.success) { |
| | | this.$Message.success("添加成功"); |
| | | |
| | | this.formAdd = { |
| | | // 添加或编辑表单对象初始化数据 |
| | | parentId: "", |
| | | sortNum: 1, |
| | | level: 0, |
| | | tagTypeName: "", |
| | | }; |
| | | } else { |
| | | // this.$Message.error(res.message); |
| | | } |
| | | this.getAllList(); |
| | | this.modalVisible = false; |
| | | }); |
| | | } else { |
| | | // 编辑 |
| | | updateTagType(this.formAdd, this.formAdd.id).then((res) => { |
| | | this.submitLoading = false; |
| | | if (res.success) { |
| | | this.$Message.success("修改成功"); |
| | | } else { |
| | | // this.$Message.error(res.message); |
| | | } |
| | | this.getAllList(); |
| | | this.modalVisible = false; |
| | | this.$refs.formAdd.resetFields(); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | // 删除分类 |
| | | remove(v) { |
| | | this.$Modal.confirm({ |
| | | title: "确认删除", |
| | | content: "您确认要删除 " + v.tagTypeName + " ?", |
| | | loading: true, |
| | | onOk: () => { |
| | | // 删除 |
| | | deleteTagTypeById(v.id).then((res) => { |
| | | this.$Modal.remove(); |
| | | if (res.code===200) { |
| | | this.$Message.success("操作成功"); |
| | | this.getAllList(); |
| | | } |
| | | }); |
| | | }, |
| | | }); |
| | | }, |
| | | // 获取分类数据 |
| | | getAllList(newval) { |
| | | this.loading = true; |
| | | getTagTypeList().then((res) => { |
| | | this.loading = false; |
| | | if (res.code===200) { |
| | | // 仅展开指定级数 默认后台已展开所有 |
| | | let expandLevel = this.expandLevel; |
| | | res.data.forEach(function (e) { |
| | | if (expandLevel == 1) { |
| | | if (e.level == 0) { |
| | | e.expand = false; |
| | | } |
| | | if (e.children && e.children.length > 0) { |
| | | e.children.forEach(function (c) { |
| | | if (c.level == 1) { |
| | | c.expand = false; |
| | | } |
| | | if (c.children && c.children.length > 0) { |
| | | c.children.forEach(function (b) { |
| | | if (b.level == 2) { |
| | | b.expand = false; |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | } else if (expandLevel == 2) { |
| | | if (e.level == 0) { |
| | | e.expand = true; |
| | | } |
| | | if (e.children && e.children.length > 0) { |
| | | e.children.forEach(function (c) { |
| | | if (c.level == 1) { |
| | | c.expand = false; |
| | | } |
| | | if (c.children && c.children.length > 0) { |
| | | c.children.forEach(function (b) { |
| | | if (b.level == 2) { |
| | | b.expand = false; |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | } else if (expandLevel == 3) { |
| | | if (e.level == 0) { |
| | | e.expand = true; |
| | | } |
| | | if (e.children && e.children.length > 0) { |
| | | e.children.forEach(function (c) { |
| | | if (c.level == 1) { |
| | | c.expand = true; |
| | | } |
| | | if (c.children && c.children.length > 0) { |
| | | c.children.forEach(function (b) { |
| | | if (b.level == 2) { |
| | | b.expand = false; |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | this.tableData = res.data; |
| | | } |
| | | }); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.init(); |
| | | }, |
| | | }; |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .article { |
| | | font-size: 16px; |
| | | font-weight: 400; |
| | | margin: 12px 0; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="wrapper"> |
| | | <Row> |
| | | <Col span="4"> |
| | | <Card style="height: 100%;" class="article-category mr_10"> |
| | | <Tree :data="treeData" @on-select-change="handleCateChange"></Tree> |
| | | </Card> |
| | | </Col> |
| | | <Col span="20"> |
| | | <Card class="article-detail"> |
| | | <Row @keydown.enter.native="handleSearch"> |
| | | <Form ref="searchForm" :model="searchForm" inline :label-width="70" style="width: 100%" class="search-form"> |
| | | <Form-item label="标签名称" prop="tagName"> |
| | | <Input type="text" v-model="searchForm.tagName" placeholder="请输入标签名称" clearable style="width: 200px" /> |
| | | </Form-item> |
| | | <Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button> |
| | | </Form> |
| | | </Row> |
| | | <Row class="operation padding-row"> |
| | | <Button @click="add" v-if="!selected" type="primary">添加</Button> |
| | | </Row> |
| | | <Table :loading="loading" border :columns="columns" :data="data" style="height: calc(100vh - 328px);" |
| | | ref="table"> |
| | | <!-- 页面展示 --> |
| | | <template slot="openStatusSlot" slot-scope="scope"> |
| | | <div></div> |
| | | <i-switch size="large" v-model="scope.row.openStatus" @on-change="changeSwitch(scope.row)"> |
| | | <span slot="open">展示</span> |
| | | <span slot="close">隐藏</span> |
| | | </i-switch> |
| | | </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> |
| | | </Page> |
| | | </Row> |
| | | </Card> |
| | | </Col> |
| | | </Row> |
| | | <template v-if="!selected"> |
| | | <Modal :tagName="modalTitle" v-model="modalVisible" :mask-closable="false" :width="1100"> |
| | | <Form ref="form" :model="form" :label-width="100"> |
| | | <FormItem label="标签名称" prop="tagName"> |
| | | <Input v-model="form.tagName" clearable style="width: 40%" /> |
| | | </FormItem> |
| | | <FormItem label="标签分类" prop="tagTypeId"> |
| | | <Select v-model="treeValue" placeholder="请选择" clearable style="width: 180px"> |
| | | <Option v-if="treeValue" :value="treeValue" style="display: none">{{ treeValue }} |
| | | </Option> |
| | | <Tree :data="treeDataDefault" @on-select-change="handleCheckChange"></Tree> |
| | | </Select> |
| | | </FormItem> |
| | | <FormItem label="排序" prop="sortNum"> |
| | | <Input type="number" v-model="form.sortNum" clearable style="width: 10%" /> |
| | | </FormItem> |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="modalVisible = false">取消</Button> |
| | | <Button type="primary" :loading="submitLoading" @click="handleSubmit">提交</Button> |
| | | </div> |
| | | </Modal> |
| | | </template> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getTagTypeList } from "@/api/tag-type"; |
| | | import { getTags, deleteTagById, editTag, addTag } from "@/api/tag"; |
| | | import tinymec from "@/components/editor/index.vue"; |
| | | export default { |
| | | components: { |
| | | tinymec: tinymec, |
| | | }, |
| | | props: { |
| | | selected: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | selectedIndex: 99999, // 已选下标 |
| | | loading: true, // 表单加载状态 |
| | | modalType: 0, // 添加或编辑标识 |
| | | modalVisible: false, // 添加或编辑显示 |
| | | modalTitle: "", // 添加或编辑标题 |
| | | treeDataDefault: [], |
| | | searchForm: { |
| | | // 搜索框初始化对象 |
| | | pageNumber: 1, // 当前页数 |
| | | pageSize: 10, // 页面大小 |
| | | sortNum: "createTime", // 默认排序字段 |
| | | order: "desc", // 默认排序方式 |
| | | tagTypeId: "", |
| | | }, |
| | | searchTreeValue: "", // 切换 |
| | | form: { |
| | | // 添加或编辑表单对象初始化数据 |
| | | tagName: "", |
| | | tagTypeId: "", |
| | | sortNum: 1, |
| | | id: "", |
| | | }, |
| | | list: [], // 列表 |
| | | treeValue: "", // 选择的分类 |
| | | //树结构 |
| | | treeData: [], |
| | | submitLoading: false, // 添加或编辑提交状态 |
| | | columns: [ |
| | | // 表头 |
| | | { |
| | | title: "分类名称", |
| | | key: "tagTypeName", |
| | | width: 150, |
| | | }, |
| | | { |
| | | title: "标签名称", |
| | | key: "tagName", |
| | | minWidth: 200, |
| | | tooltip: true, |
| | | }, |
| | | { |
| | | title: "排序", |
| | | key: "sortNum", |
| | | width: 100, |
| | | }, |
| | | { |
| | | title: "操作", |
| | | key: "action", |
| | | align: "center", |
| | | |
| | | width: 230, |
| | | render: (h, params) => { |
| | | return h("div", [ |
| | | h( |
| | | "Button", |
| | | { |
| | | props: { |
| | | size: "small", |
| | | type: |
| | | this.selectedIndex == params.index |
| | | ? "primary" |
| | | : "default", |
| | | }, |
| | | style: { |
| | | marginRight: "5px", |
| | | display: this.selected ? "" : "none", |
| | | }, |
| | | on: { |
| | | click: () => { |
| | | this.selectedIndex = params.index; |
| | | this.$emit("callbacked", params.row); |
| | | }, |
| | | }, |
| | | }, |
| | | this.selectedIndex == params.index ? "已选" : "选择" |
| | | ), |
| | | h( |
| | | "Button", |
| | | { |
| | | props: { |
| | | size: "small", |
| | | type: "info", |
| | | }, |
| | | style: { |
| | | marginRight: "5px", |
| | | }, |
| | | on: { |
| | | click: () => { |
| | | this.edit(params.row); |
| | | }, |
| | | }, |
| | | }, |
| | | "编辑" |
| | | ), |
| | | h( |
| | | "Button", |
| | | { |
| | | props: { |
| | | type: "error", |
| | | size: "small", |
| | | }, |
| | | on: { |
| | | click: () => { |
| | | this.remove(params.row); |
| | | }, |
| | | }, |
| | | }, |
| | | "删除" |
| | | ), |
| | | ]); |
| | | }, |
| | | }, |
| | | ], |
| | | data: [], // 表单数据 |
| | | total: 0, // 表单数据总数 |
| | | }; |
| | | }, |
| | | watch: { |
| | | "searchForm.tagTypeId": { |
| | | handler() { |
| | | this.handleSearch(); |
| | | }, |
| | | deep: true, |
| | | }, |
| | | "searchForm.tagName": { |
| | | handler() { |
| | | this.handleSearch(); |
| | | }, |
| | | deep: true, |
| | | }, |
| | | }, |
| | | methods: { |
| | | // 初始化数据 |
| | | init() { |
| | | this.getDataList(); |
| | | this.getAllList(0); |
| | | }, |
| | | // 选择分类回调 |
| | | handleCateChange(data) { |
| | | let { value, title } = data[0]; |
| | | this.list.push({ |
| | | value, |
| | | title, |
| | | }); |
| | | this.searchForm.tagTypeId = value; |
| | | this.searchTreeValue = title; |
| | | this.getDataList() |
| | | }, |
| | | // 标签分类的选择事件 |
| | | handleCheckChange(data) { |
| | | let value = ""; |
| | | let title = ""; |
| | | this.list = []; |
| | | data.forEach((item, index) => { |
| | | value += `${item.value},`; |
| | | title += `${item.title},`; |
| | | }); |
| | | value = value.substring(0, value.length - 1); |
| | | title = title.substring(0, title.length - 1); |
| | | this.list.push({ |
| | | value, |
| | | title, |
| | | }); |
| | | this.form.tagTypeId = value; |
| | | this.treeValue = title; |
| | | }, |
| | | // 改变页数 |
| | | changePage(v) { |
| | | this.searchForm.pageNumber = v; |
| | | this.getDataList(); |
| | | }, |
| | | // 改变页码 |
| | | changePageSize(v) { |
| | | this.selected.pageNumber = 1; |
| | | this.searchForm.pageSize = v; |
| | | this.getDataList(); |
| | | }, |
| | | // 搜索列表 |
| | | handleSearch() { |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = 10; |
| | | this.getDataList(); |
| | | }, |
| | | // 获取全部标签分类 |
| | | getAllList(parent_id) { |
| | | this.loading = true; |
| | | getTagTypeList(parent_id).then((res) => { |
| | | this.loading = false; |
| | | if (res.code == 200) { |
| | | this.treeData = this.getTree(res.data); |
| | | this.treeDataDefault = this.getTree(res.data); |
| | | this.treeData.unshift({ |
| | | title: "全部", |
| | | level: 0, |
| | | children: [], |
| | | id: "0", |
| | | tagTypeId: 0, |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // 标签分类格式化方法 |
| | | getTree(tree = []) { |
| | | let arr = []; |
| | | if (!!tree && tree.length !== 0) { |
| | | tree.forEach((item) => { |
| | | let obj = {}; |
| | | obj.title = item.tagTypeName; |
| | | obj.value = item.id; |
| | | obj.attr = item.tagTypeName; // 其他你想要添加的属性 |
| | | obj.expand = false; |
| | | obj.selected = false; |
| | | obj.children = this.getTree(item.children); // 递归调用 |
| | | arr.push(obj); |
| | | }); |
| | | } |
| | | return arr; |
| | | }, |
| | | // 获取标签列表 |
| | | getDataList(val) { |
| | | if (val) this.form = {}; |
| | | this.loading = true; |
| | | getTags(this.searchForm).then((res) => { |
| | | this.loading = false; |
| | | if (res.code === 200) { |
| | | this.total = res.total; |
| | | //为了在是否展示一列展示开关 需要改一下数据类型,最终提交再次更改 |
| | | this.data = []; |
| | | if (res.data.length > 0) { |
| | | this.data = res.data; |
| | | } |
| | | } |
| | | }); |
| | | this.total = this.data?.length; |
| | | this.loading = false; |
| | | }, |
| | | // 添加标签 |
| | | handleSubmit() { |
| | | this.$refs.form.validate((valid) => { |
| | | if (valid) { |
| | | this.submitLoading = true; |
| | | if (this.modalType === 0) { |
| | | // 添加 避免编辑后传入id等数据 记得删除 |
| | | delete this.form.id; |
| | | addTag(this.form).then((res) => { |
| | | this.submitLoading = false; |
| | | if (res.code === 200) { |
| | | this.$Message.success("操作成功"); |
| | | this.getDataList(); |
| | | this.modalVisible = false; |
| | | } |
| | | }); |
| | | } else { |
| | | // 编辑 |
| | | editTag(this.form).then((res) => { |
| | | this.submitLoading = false; |
| | | if (res.code === 200) { |
| | | this.$Message.success("操作成功"); |
| | | this.getDataList(); |
| | | this.modalVisible = false; |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | // 添加标签modal |
| | | add() { |
| | | this.modalType = 0; |
| | | this.modalTitle = "添加标签"; |
| | | this.treeValue = ""; |
| | | |
| | | this.form = { |
| | | sortNum: 1, |
| | | tagName: "", |
| | | }; |
| | | this.$refs.form.resetFields(); |
| | | delete this.form.id; |
| | | this.modalVisible = true; |
| | | }, |
| | | // 编辑标签modal |
| | | edit(data) { |
| | | this.modalType = 1; |
| | | this.modalTitle = "编辑标签"; |
| | | this.treeValue = ""; |
| | | this.form = { |
| | | tagName: "", |
| | | }; |
| | | this.$refs.form.resetFields(); |
| | | |
| | | this.modalVisible = true; |
| | | this.form.tagTypeId = data.tagTypeId; |
| | | this.treeValue = data.tagTypeName; |
| | | this.form.id = data.id; |
| | | this.form.tagName = data.tagName; |
| | | this.form.sortNum = data.sortNum; |
| | | }, |
| | | // 删除标签 |
| | | remove(v) { |
| | | this.$Modal.confirm({ |
| | | tagName: "确认删除", |
| | | content: "您确认要删除么?", |
| | | loading: true, |
| | | onOk: () => { |
| | | // 删除 |
| | | deleteTagById(v.id).then((res) => { |
| | | this.$Modal.remove(); |
| | | if (res.code === 200) { |
| | | this.$Message.success("操作成功"); |
| | | this.getDataList(); |
| | | } |
| | | }); |
| | | }, |
| | | }); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.init(); |
| | | }, |
| | | }; |
| | | </script> |
| | |
| | | "@amap/amap-jsapi-loader": "0.0.7", |
| | | "@antv/g2": "^4.1.14", |
| | | "axios": "^0.21.1", |
| | | "cos-js-sdk-v5": "^1.10.1", |
| | | "dplayer": "^1.27.1", |
| | | "js-cookie": "^2.2.1", |
| | | "node-sass": "^4.14.1", |
| New file |
| | |
| | | import service, { |
| | | getRequest, |
| | | postRequest, |
| | | putRequest, |
| | | deleteRequest, |
| | | importRequest, |
| | | getRequestWithNoToken, |
| | | commonUrl, |
| | | postRequestWithNoForm |
| | | } from "@/libs/axios"; |
| | | |
| | | |
| | | // 获取文件临时访问url |
| | | export const getFilePreview = (fileKey) => { |
| | | return service({ |
| | | baseURL: commonUrl, |
| | | url: "/common/lmk/file/preview", |
| | | method: "POST", |
| | | data: {"fileKey": fileKey} |
| | | }) |
| | | } |
| | | |
| | | // 获取STS访问令牌 |
| | | export const getSts = () => { |
| | | return service({ |
| | | baseURL: commonUrl, |
| | | url: "/common/lmk/file/sts", |
| | | method: "GET" |
| | | }) |
| | | } |
| | | |
| | |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 原始的axios暴露出去用即可 |
| | | export default service |
| | | export const uploadFileRequest = (url, params) => { |
| | | let accessToken = getStore("accessToken"); |
| | | return service({ |
| New file |
| | |
| | | |
| | | /** |
| | | * 生成fileKey |
| | | * |
| | | * @param fileName 文件名 |
| | | * @returns {*} |
| | | */ |
| | | export function getFileKey (fileName) { |
| | | const extension = fileName.split('.').pop().toLowerCase(); |
| | | |
| | | const fileTypes = { |
| | | image: { name: '图片', exts: ["jpg", "png", "jpeg", "gif", "bmp", "webp", "tiff", "svg", "ico", "psd", "raw"] }, |
| | | video: { name: '视频', exts: ["mp4", "avi", "rmvb", "mov", "wmv", "flv", "mkv", "mpeg", "mpg", "m4v", "3gp", "webm", "vob", "swf"] }, |
| | | radio: { name: '音频', exts: ["mp3", "wma", "wav", "mpeg-4", "cd", "m4a", "aac", "flac", "ogg", "aiff", "ape", "midi", "amr", "ra"] }, |
| | | text: { name: '文本', exts: ["txt", "xls", "xlsx", "doc", "docx", "pdf", "ppt", "pptx", "csv", "rtf", "odt", "ods", "odp", "epub", "mobi", "pages", "numbers", "key"] }, |
| | | zip: { name: '压缩文件', exts: ["zip", "rar", "7z", "tar", "gz", "bz2", "xz", "iso", "dmg", "pkg", "cab", "z", "lz", "lzma", "lzo"] } |
| | | }; |
| | | |
| | | // 获取当前时间并格式化为 yyyyMMddHHmmss |
| | | const now = new Date(); |
| | | const yyyyMMddHHmmss = [ |
| | | now.getFullYear(), |
| | | String(now.getMonth() + 1).padStart(2, '0'), |
| | | String(now.getDate()).padStart(2, '0'), |
| | | String(now.getHours()).padStart(2, '0'), |
| | | String(now.getMinutes()).padStart(2, '0'), |
| | | String(now.getSeconds()).padStart(2, '0') |
| | | ].join(''); |
| | | |
| | | // 生成5位随机数字 |
| | | const random5Digits = Math.floor(10000 + Math.random() * 90000); |
| | | |
| | | // 查找匹配的文件类型 |
| | | for (const [type, data] of Object.entries(fileTypes)) { |
| | | if (data.exts.includes(extension)) { |
| | | return `${type}/${yyyyMMddHHmmss}${random5Digits}` + '.' + extension; |
| | | } |
| | | } |
| | | return ''; |
| | | } |
| | |
| | | <template slot="goodsSlot" slot-scope="{ row }"> |
| | | <div style="margin-top: 5px; height: 90px; display: flex"> |
| | | <div style=""> |
| | | <img |
| | | <img v-if="row.original" |
| | | :src="row.original" |
| | | style="height: 80px; margin-top: 3px; width: 70px" |
| | | /> |
| | | <video :src="row.goodsVideo" v-else style="height: 80px; margin-top: 3px; width: 70px"></video> |
| | | </div> |
| | | |
| | | <div style="margin-left: 13px"> |
| | |
| | | <second-step ref='second' :firstData="firstData" v-if="activestep === 1"></second-step> |
| | | <!-- 第三步 发布完成 --> |
| | | <third-step ref='third' v-if="activestep === 2"></third-step> |
| | | |
| | | |
| | | |
| | | |
| | | </div> |
| | | </template> |
| | | <script> |
| | |
| | | this.activestep = 0 |
| | | this.$refs.first.selectGoodsType = true; |
| | | } |
| | | |
| | | |
| | | } |
| | | }; |
| | | </script> |
| | |
| | | type: "PHYSICAL_GOODS", |
| | | check: false, |
| | | }, |
| | | { |
| | | title: "虚拟商品", |
| | | img: require("@/assets/goodsType2.png"), |
| | | desc: "虚拟核验,无需物流", |
| | | type: "VIRTUAL_GOODS", |
| | | check: false, |
| | | }, |
| | | { |
| | | title: "商品模板导入", |
| | | img: require("@/assets/goodsTypeTpl.png"), |
| | | desc: "商品模板,一键导入", |
| | | check: false, |
| | | }, |
| | | // { |
| | | // title: "虚拟商品", |
| | | // img: require("@/assets/goodsType2.png"), |
| | | // desc: "虚拟核验,无需物流", |
| | | // type: "VIRTUAL_GOODS", |
| | | // check: false, |
| | | // }, |
| | | // { |
| | | // title: "商品模板导入", |
| | | // img: require("@/assets/goodsTypeTpl.png"), |
| | | // desc: "商品模板,一键导入", |
| | | // check: false, |
| | | // }, |
| | | ], |
| | | // 商品分类选择数组 |
| | | category: [ |
| | |
| | | { name: "", id: "" }, |
| | | ], |
| | | // 商品类型 |
| | | goodsType: "", |
| | | // goodsType: "", |
| | | goodsType: "PHYSICAL_GOODS", |
| | | /** 1级分类列表*/ |
| | | categoryListLevel1: [], |
| | | /** 2级分类列表*/ |
| | |
| | | if (!this.category[0].name) { |
| | | this.$Message.error("请选择商品分类"); |
| | | return; |
| | | } else if (!this.category[2].name) { |
| | | this.$Message.error("必须选择到三级分类"); |
| | | return; |
| | | } else if (this.category[2].name) { |
| | | } |
| | | //关闭必须选择3个流程的选项 |
| | | // else if (!this.category[2].name) { |
| | | // this.$Message.error("必须选择到三级分类"); |
| | | // return; |
| | | // } |
| | | else if (this.category[2].name) { |
| | | let params = { |
| | | category: this.category, |
| | | goodsType: this.goodsType, |
| | |
| | | this.$emit("change", params); |
| | | } |
| | | } |
| | | //流程调整 |
| | | else { |
| | | let params = { |
| | | category: this.category, |
| | | goodsType: this.goodsType, |
| | | }; |
| | | this.$emit("change", params); |
| | | } |
| | | }, |
| | | }, |
| | | mounted() { |
| | |
| | | <FormItem label="商品卖点" prop="sellingPoint"> |
| | | <Input v-model="baseInfoForm.sellingPoint" :rows="4" style="width: 260px" type="textarea"/> |
| | | </FormItem> |
| | | <FormItem label="商品品牌" prop="brandId"> |
| | | <Select v-model="baseInfoForm.brandId" filterable style="width: 200px"> |
| | | <Option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"></Option> |
| | | </Select> |
| | | <Button class="refresh-icon" icon="md-refresh" shape="circle" type="text" |
| | | @click="refresh('brand')"></Button> |
| | | </FormItem> |
| | | <!-- <FormItem label="商品品牌" prop="brandId">--> |
| | | <!-- <Select v-model="baseInfoForm.brandId" filterable style="width: 200px">--> |
| | | <!-- <Option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"></Option>--> |
| | | <!-- </Select>--> |
| | | <!-- <Button class="refresh-icon" icon="md-refresh" shape="circle" type="text"--> |
| | | <!-- @click="refresh('brand')"></Button>--> |
| | | <!-- </FormItem>--> |
| | | </div> |
| | | <h4>商品交易信息</h4> |
| | | <div class="form-item-view"> |
| | |
| | | </div> |
| | | <h4>商品规格及图片</h4> |
| | | <div class="form-item-view"> |
| | | <FormItem class="form-item-view-el required" label="主图" prop="goodsGalleryFiles"> |
| | | <FormItem class="form-item-view-el required" label="主图" prop="goodsGalleryFiles" > |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | | <vuedraggable :animation="200" :list="baseInfoForm.goodsGalleryFiles"> |
| | | <div v-for="(item, __index) in baseInfoForm.goodsGalleryFiles" :key="__index" |
| | | <vuedraggable :animation="200" :list="showListImages"> |
| | | <div v-for="(item, __index) in showListImages" :key="__index" |
| | | class="demo-upload-list"> |
| | | <template> |
| | | <img :src="item"/> |
| | |
| | | </div> |
| | | </vuedraggable> |
| | | <!--<Upload ref="upload"--> |
| | | <!--:action="uploadFileUrl" :before-upload="handleBeforeUploadGoodsPicture"--> |
| | | <!--:format="['jpg', 'jpeg', 'png', 'webp']"--> |
| | | <!--:headers="{ ...accessToken }"--> |
| | | <!--:max-size="2048" :on-error="() => { $Spin.hide(); }" :on-exceeded-size="handleMaxSize"--> |
| | | <!--:on-format-error="handleFormatError" :on-progress="() => { $Spin.show(); }"--> |
| | | <!--:on-success="handleSuccessGoodsPicture" :show-upload-list="false" multiple--> |
| | | <!--style="margin-left: 10px"--> |
| | | <!--type="drag">--> |
| | | <!--<div style="width: 148px; height: 148px; line-height: 148px">--> |
| | | <!--<Icon size="20" type="md-add"></Icon>--> |
| | | <!--</div>--> |
| | | <!--:action="uploadFileUrl" :before-upload="handleBeforeUploadGoodsPicture"--> |
| | | <!--:format="['jpg', 'jpeg', 'png', 'webp']"--> |
| | | <!--:headers="{ ...accessToken }"--> |
| | | <!--:max-size="2048" :on-error="() => { $Spin.hide(); }" :on-exceeded-size="handleMaxSize"--> |
| | | <!--:on-format-error="handleFormatError" :on-progress="() => { $Spin.show(); }"--> |
| | | <!--:on-success="handleSuccessGoodsPicture" :show-upload-list="false" multiple--> |
| | | <!--style="margin-left: 10px"--> |
| | | <!--type="drag">--> |
| | | <!--<div style="width: 148px; height: 148px; line-height: 148px">--> |
| | | <!--<Icon size="20" type="md-add"></Icon>--> |
| | | <!--</div>--> |
| | | <!--</Upload>--> |
| | | </div> |
| | | <div style="width: 100%;display: flex;justify-content: start;margin-top: 10px;"> |
| | |
| | | </Modal> |
| | | </FormItem> |
| | | <FormItem> |
| | | <div style="color: grey">主图仅支持png,jpg,jpeg格式,宽高至少600*600px,大小2M内,可拖拽调整主图顺序</div> |
| | | |
| | | <!-- <div class="demo-upload-list" v-for="(item,index) in showListImages">--> |
| | | <!-- <template style="display: flex">--> |
| | | <!-- <img :src="item">--> |
| | | <!-- <div class="demo-upload-list-cover">--> |
| | | <!-- <Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon>--> |
| | | <!-- <Icon type="ios-trash-outline" @click.native="handleRemove(index)"></Icon>--> |
| | | <!-- </div>--> |
| | | <!-- </template>--> |
| | | <!-- </div>--> |
| | | <div style="color: grey" v-if="!baseInfoForm.goodsVideo">主图仅支持png,jpg,jpeg格式,宽高至少600*600px,大小2M内</div> |
| | | </FormItem> |
| | | <FormItem class="form-item-view-el" label="主图视频" prop="goodsVideo"> |
| | | <FormItem class="form-item-view-el" label="视频" prop="goodsVideo" > |
| | | <div class="goods-video"> |
| | | <div v-if="baseInfoForm.goodsVideo"> |
| | | <div> |
| | | <video :src="baseInfoForm.goodsVideo" class="video" controls style="max-width: 300px;"/> |
| | | <video :src="baseInfoForm.showGoodsVideo" class="video" controls style="max-width: 300px;"/> |
| | | </div> |
| | | </div> |
| | | <Upload ref="upload" :action="uploadFileUrl" :format="['avi', 'wmv', 'mpeg', 'mp4', 'mov']" |
| | | <Upload ref="upload" action="-" :format="['avi', 'wmv', 'mpeg', 'mp4', 'mov']" |
| | | :headers="{ ...accessToken }" |
| | | :max-size="10240" :on-error="() => { loadingVideo = false }" |
| | | :on-exceeded-size="handleVideoMaxSize" |
| | | :on-format-error="handleFormatError" :on-progress="() => { loadingVideo = true }" |
| | | :on-success="handleSuccessGoodsVideo" :show-upload-list="false" |
| | | multiple |
| | | :before-upload="upLoadVideo" |
| | | accept="video/*" |
| | | style="margin-left: 10px" type="drag"> |
| | | <Button :loading="loadingVideo" icon="ios-cloud-upload-outline" type="text"> |
| | | <span v-if="!loadingVideo"> |
| | |
| | | </span> |
| | | </Button> |
| | | </Upload> |
| | | <Button :loading="loadingVideo" v-if="baseInfoForm.goodsVideo" icon="delete" @click="removeVideo" type="text"> |
| | | <span>删除视频</span> |
| | | </Button> |
| | | </div> |
| | | </FormItem> |
| | | <div class="layout" style="width: 100%"> |
| | |
| | | <div v-for="(item, $index) in skuInfo" :key="$index" class="sku-item-content"> |
| | | <Card :bordered="true" class="ivu-card-body"> |
| | | <a slot="extra" style="margin-left: 6px"> |
| | | <Icon size="20" type="md-trash" @click="handleCloseSkuItem($index, item)"></Icon> |
| | | <Icon size="20" type="md-trash" @click="handleCloseSkuItem($index, item)"></Icon> |
| | | </a> |
| | | <div> |
| | | <div style="display: flex;margin-bottom: 10px;font-weight: bold">规格项</div> |
| | |
| | | <div> |
| | | <AutoComplete v-model="item.name" :filter-method="filterMethod" |
| | | :maxlength="30" placeholder="请输入规格项名称" style="width: 150px" |
| | | @on-focus="changeSkuItem(item.name)" @on-change="editSkuItem(item.name, $index, item)"> |
| | | @on-focus="changeSkuItem(item.name)" |
| | | @on-change="editSkuItem(item.name, $index, item)"> |
| | | </AutoComplete> |
| | | |
| | | <iSwitch v-if="$index === 0" style="margin-left: 10px" size="small" @on-change="changeSkuOpenImage" v-model="openImage" /><span v-if="$index === 0" style="margin-left: 5px">添加规格图片</span> |
| | | <!-- <iSwitch v-if="$index === 0" style="margin-left: 10px" size="small"--> |
| | | <!-- @on-change="changeSkuOpenImage" v-model="openImage"/>--> |
| | | <!-- <span v-if="$index === 0" style="margin-left: 5px">添加规格图片</span>--> |
| | | </div> |
| | | </FormItem> |
| | | |
| | |
| | | @on-change="skuValueChange(val, index, item)"> |
| | | </AutoComplete> |
| | | <a style="margin-left: 6px" v-if="val.value && val.value !== ''"> |
| | | <Icon size="15" type="md-trash" @click="handleCloseSkuValue(val, index, item)"></Icon> |
| | | <Icon size="15" type="md-trash" |
| | | @click="handleCloseSkuValue(val, index, item)"></Icon> |
| | | </a> |
| | | </div> |
| | | <div v-if="$index === 0 && openImage" style="margin-top: 10px"> |
| | |
| | | style="width: 180px;height: 140px" |
| | | /> |
| | | <div class="sku-upload-list-cover"> |
| | | <div style="margin-top: 50px" > |
| | | <div style="margin-top: 50px"> |
| | | <Icon size="25" type="md-search" @click="handleView(img)"></Icon> |
| | | <Icon size="25" type="md-trash" @click="handleRemove(val.images, __index)"></Icon> |
| | | <Icon size="25" type="md-trash" |
| | | @click="handleRemove(val.images, __index)"></Icon> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | </vuedraggable> |
| | | <Upload ref="uploadSku" :action="uploadFileUrl" |
| | | <!-- todo 3--> |
| | | <Upload ref="uploadSku" action="-" |
| | | v-if="val.images < 1" |
| | | :before-upload="handleBeforeUpload" |
| | | :format="['jpg', 'jpeg', 'png', 'webp']" |
| | | :headers="{ ...accessToken }" |
| | | :max-size="2048" |
| | | :on-error="() => { $Spin.hide(); }" |
| | | :on-exceeded-size="handleMaxSize" |
| | |
| | | </div> |
| | | </FormItem> |
| | | |
| | | <FormItem v-if="item.spec_values.length < 10 && item.spec_values.length >= 1 && item.spec_values[0].value !== ''" class="sku-item-content-val flex" label="" style="line-height: 32px;"> |
| | | <FormItem |
| | | v-if="item.spec_values.length < 10 && item.spec_values.length >= 1 && item.spec_values[0].value !== ''" |
| | | class="sku-item-content-val flex" label="" style="line-height: 32px;"> |
| | | <AutoComplete ref="input" v-model="newSkuValues[$index]" |
| | | :filter-method="filterMethod" |
| | | :maxlength="30" placeholder="自定义规格值" style="width: 180px" |
| | |
| | | </div> |
| | | <FormItem class="form-item-view-el" label="PC商品描述" prop="intro" style="width: 100%"> |
| | | <editor |
| | | :show-upload="false" |
| | | ref="editor" |
| | | v-model="baseInfoForm.intro" |
| | | height="800px" |
| | |
| | | |
| | | <FormItem class="form-item-view-el" label="移动端描述" prop="skuList" style="width: 100%"> |
| | | <editor |
| | | :show-upload="false" |
| | | ref="introEditor" |
| | | v-model="baseInfoForm.mobileIntro" |
| | | height="800px" |
| | |
| | | <!--<Modal width="1200px" v-model="picModelFlag">--> |
| | | <!--<ossManage @callback="callbackSelected" ref="ossManage" />--> |
| | | <!--</Modal>--> |
| | | <Modal v-model="picModelFlag" width="1200px" @on-ok="confirmUrls"> |
| | | <ossManage ref="ossManage" :isComponent="true" :initialize="picModelFlag" @callback="callbackSelected" @selected="(list)=>{ selectedImage = list}"/> |
| | | <!-- todo web--> |
| | | <Modal v-model="picModelFlag" width="1200px"> |
| | | <!-- <ossManage ref="ossManRage" :isComponent="true" :initialize="picModelFlag" @callback="callbackSelected" @selected="(list)=>{ selectedImage = list}"/>--> |
| | | <div class="demo-upload-list" v-for="(item,index) in showListImages"> |
| | | <template> |
| | | <img :src="item"> |
| | | <div class="demo-upload-list-cover"> |
| | | <Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon> |
| | | <Icon type="ios-trash-outline" @click.native="handleRemove(null,index)"></Icon> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | <div class="demo-upload-list"> |
| | | <Upload |
| | | :before-upload="upLoadImg" |
| | | accept="image/*" |
| | | action="-" |
| | | type="drag" |
| | | style=" display: inline-block;width: 58px" |
| | | > |
| | | <div style="width: 58px;height:58px;line-height: 58px;"> |
| | | <Icon type="ios-camera" size="20"></Icon> |
| | | </div> |
| | | </Upload> |
| | | </div> |
| | | |
| | | </Modal> |
| | | |
| | | </div> |
| | |
| | | import DPlayer from 'dplayer'; |
| | | // import ossManage from "@/views/sys/oss-manage/ossManage"; |
| | | import ossManage from "@/views/shop/ossManages"; |
| | | import COS from 'cos-js-sdk-v5'; |
| | | import {getFileKey} from "@/utils/file.js"; |
| | | import {getFilePreview, getSts} from "@/api/file"; |
| | | |
| | | |
| | | export default { |
| | |
| | | }, 1000); |
| | | }; |
| | | return { |
| | | showListImages: [], |
| | | regular, |
| | | openImage: false, |
| | | needToloadSku: false, |
| | |
| | | /** 商品分类中文名 */ |
| | | categoryName: [], |
| | | goodsVideo: "", |
| | | showGoodsVideo: "", |
| | | }, |
| | | /** 表格头 */ |
| | | skuTableColumn: [], |
| | |
| | | if (val) { |
| | | this.initVideo(); |
| | | } |
| | | }, |
| | | showListImages(newValue){ |
| | | this.baseInfoForm.goodsGalleryFiles = newValue.map(item => { |
| | | return item.split('/').slice(-2).join('/') |
| | | }) |
| | | } |
| | | }, |
| | | methods: { |
| | | // 选择图片modal |
| | | handleCLickImg(val, index) { |
| | | this.$refs.ossManage.selectImage = true; |
| | | console.log('测试输入的值----------------》', val) |
| | | // 废弃原有的图片上传 |
| | | // this.$refs.ossManage.selectImage = true; |
| | | this.picModelFlag = true; |
| | | this.selectedFormBtnName = val; |
| | | // this.picIndex = index; |
| | |
| | | }, |
| | | // ship大小不正确 |
| | | handleVideoMaxSize(file) { |
| | | this.$Notice.warning({ |
| | | title: "超过文件大小限制", |
| | | desc: "视频大小不能超过10MB", |
| | | }); |
| | | // this.$Notice.warning({ |
| | | // title: "超过文件大小限制", |
| | | // desc: "视频大小不能超过10MB", |
| | | // }); |
| | | }, |
| | | onAddSku(index) { |
| | | if (!this.newSkuValues[index]) { |
| | |
| | | }, |
| | | // 移除已选图片 |
| | | handleRemove(item, index) { |
| | | item.splice(index, 1) |
| | | if (!item) { |
| | | this.listImages.splice(index, 1); |
| | | this.showListImages.splice(index, 1); |
| | | this.baseInfoForm.goodsGalleryFiles.splice(index, 1); |
| | | this.baseInfoForm.goodsGalleryList.splice(index, 1); |
| | | } else { |
| | | console.log('移除测试',item, index); |
| | | item.splice(index, 1) |
| | | } |
| | | this.previewPicture = ""; |
| | | }, |
| | | // 查看商品大图 |
| | |
| | | } |
| | | }, |
| | | // sku图片上传前钩子 |
| | | handleBeforeUpload(file) { |
| | | async handleBeforeUpload(file) { |
| | | const check = |
| | | this.selectedSku.images !== undefined && |
| | | this.selectedSku.images.length > 5; |
| | | if (check) { |
| | | this.$Notice.warning({title: "图片数量不能大于五张"}); |
| | | return false; |
| | | } |
| | | try { |
| | | // this.upLoadVideoLoading = true; |
| | | // 获取文件上传临时密钥 |
| | | const sts = await getSts(); |
| | | const cos = new COS({ |
| | | getAuthorization: async function (options, callback) { |
| | | callback({ |
| | | TmpSecretId: sts.data.tmpSecretId, |
| | | TmpSecretKey: sts.data.tmpSecretKey, |
| | | SecurityToken: sts.data.sessionToken, |
| | | // 建议返回服务器时间作为签名的开始时间,避免客户端本地时间偏差过大导致签名错误 |
| | | StartTime: sts.data.stsStartTime, // 时间戳,单位秒,如:1580000000 |
| | | ExpiredTime: sts.data.stsEndTime,// 时间戳,单位秒,如:1580000000 |
| | | ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用 |
| | | }); |
| | | } |
| | | }) |
| | | const fileKey = getFileKey(file.name) |
| | | const upData = await cos.uploadFile({ |
| | | Bucket: sts.data.bucket, |
| | | Region: sts.data.region, |
| | | Key: fileKey, |
| | | Body: file, // 要上传的文件对象。 |
| | | SliceSize: 1024 * 1024 * 5, |
| | | onProgress: function (progressData) { |
| | | console.log('上传进度:', progressData); |
| | | }, |
| | | }); |
| | | console.log("上传成功", upData) |
| | | this.$nextTick(() => { |
| | | this.listImages.push(fileKey); |
| | | this.showListImages.push(sts.data.endpoint + "/" + fileKey); |
| | | this.baseInfoForm.goodsGalleryFiles.push(fileKey); |
| | | }) |
| | | |
| | | } catch (e) { |
| | | console.log("上传失败", upData) |
| | | return false; |
| | | } finally { |
| | | // this.upLoadVideoLoading = false; |
| | | |
| | | } |
| | | return false; |
| | | |
| | | }, |
| | | |
| | | /** 查询商品品牌列表 */ |
| | |
| | | this.baseInfoForm.goodsGalleryFiles = |
| | | response.result.goodsGalleryList.map((i) => { |
| | | return i; |
| | | }); |
| | | }) |
| | | try { |
| | | const stsInfo = await getSts(); |
| | | const endpoint = stsInfo.data.endpoint; |
| | | this.showListImages = response.result.goodsGalleryList.map((i) => { |
| | | if (i!=null&&i.indexOf('http')===-1) |
| | | return endpoint+'/'+i; |
| | | else return i; |
| | | }) |
| | | if (response.result.goodsVideo){ |
| | | |
| | | } |
| | | } catch (e) { |
| | | console.log('组装路径出问题',e); |
| | | } |
| | | |
| | | } |
| | | if (response.result.goodsVideo){ |
| | | try { |
| | | const stsInfo = await getSts(); |
| | | const endpoint = stsInfo.data.endpoint; |
| | | this.baseInfoForm.goodsVideo = response.result.goodsVideo; |
| | | this.baseInfoForm.showGoodsVideo = endpoint + '/' + response.result.goodsVideo; |
| | | console.log('显示商品视频------------------->', this.baseInfoForm.showGoodsVideo); |
| | | } catch (e) { |
| | | console.log('组装视频地址出错了') |
| | | } |
| | | } |
| | | |
| | | if ( |
| | | response.result.wholesaleList && |
| | |
| | | this.renderGoodsDetailSku(response.result.skuList); |
| | | |
| | | /** 查询品牌列表 */ |
| | | this.getGoodsBrandList(); |
| | | //todo 移除品牌概念 |
| | | // this.getGoodsBrandList(); |
| | | |
| | | /** 查询店铺商品分类 */ |
| | | this.GET_ShopGoodsLabel(); |
| | |
| | | this.firstData.goodsType && |
| | | (this.baseInfoForm.goodsType = this.firstData.goodsType); |
| | | /** 查询商品参数 */ |
| | | this.GET_GoodsParams(); |
| | | // this.GET_GoodsParams(); |
| | | }, |
| | | // 渲染sku数据 |
| | | renderGoodsDetailSku(skuList) { |
| | |
| | | }, |
| | | /** 添加商品 **/ |
| | | save() { |
| | | this.submitLoading = true; |
| | | this.$refs["baseInfoForm"].validate((valid) => { |
| | | if (valid) { |
| | | if (this.baseInfoForm.salesModel === "WHOLESALE") { |
| | | for (let i = 0; i < this.wholesaleData.length; i++) { |
| | | this.checkWholesaleNum(i); |
| | | this.checkWholesalePrice(i); |
| | | this.wholesaleData[i].goodsId = this.goodsId; |
| | | } |
| | | this.baseInfoForm.wholesaleList = this.wholesaleData; |
| | | } |
| | | this.baseInfoForm.goodsId = this.goodsId; |
| | | let submit = JSON.parse(JSON.stringify(this.baseInfoForm)); |
| | | if ( |
| | | submit.goodsGalleryFiles && |
| | | submit.goodsGalleryFiles.length <= 0 |
| | | ) { |
| | | this.submitLoading = false; |
| | | this.$Message.error("请上传商品图片"); |
| | | return; |
| | | } |
| | | if (submit.templateId === "") submit.templateId = 0; |
| | | let flag = false; |
| | | let paramValue = ""; |
| | | |
| | | if (flag) { |
| | | this.$Message.error(paramValue + " 参数值不能为空"); |
| | | this.submitLoading = false; |
| | | return; |
| | | } |
| | | |
| | | if (this.goodsUnitList && !this.goodsUnitList.find(i => i === this.baseInfoForm.goodsUnit)) { |
| | | submit.goodsUnit = "" |
| | | this.$Message.error("商品单位不存在"); |
| | | this.submitLoading = false; |
| | | return; |
| | | } |
| | | let skuInfoNames = this.skuInfo.map((n) => n.name); |
| | | submit.skuList = []; |
| | | let containEmptyImage = false; |
| | | this.skuTableData.map((sku) => { |
| | | let skuCopy = { |
| | | cost: 1, |
| | | price: sku.price, |
| | | quantity: sku.quantity, |
| | | // alertQuantity: sku.alertQuantity, |
| | | sn: sku.sn, |
| | | images: [], |
| | | }; |
| | | if (this.openImage) { |
| | | this.skuInfo[0].spec_values.forEach(item => { |
| | | if (!item.images || item.images.length === 0) { |
| | | containEmptyImage = true; |
| | | return; |
| | | } |
| | | if (item.value === sku[this.skuInfo[0].name]) { |
| | | skuCopy.images = item.images |
| | | } |
| | | }) |
| | | |
| | | } |
| | | if (sku.weight) { |
| | | skuCopy.weight = sku.weight; |
| | | } |
| | | if (this.baseInfoForm.weight) { |
| | | skuCopy.weight = this.baseInfoForm.weight; |
| | | } |
| | | if (sku.id) { |
| | | skuCopy.id = sku.id; |
| | | } |
| | | for (let skuInfoName of skuInfoNames) { |
| | | skuCopy[skuInfoName] = sku[skuInfoName]; |
| | | } |
| | | submit.skuList.push(skuCopy); |
| | | }); |
| | | if (containEmptyImage) { |
| | | this.$Message.error("开启规格图片,所有规格图片不能为空!"); |
| | | this.submitLoading = false; |
| | | return; |
| | | } |
| | | if (submit.goodsGalleryFiles.length > 0) { |
| | | submit.goodsGalleryList = submit.goodsGalleryFiles.map( |
| | | (i) => i |
| | | ); |
| | | } |
| | | /** 参数校验 **/ |
| | | /* Object.keys(submit.goodsParamsList).forEach((item) => { |
| | | });*/ |
| | | submit.release ? (submit.release = true) : (submit.release = false); |
| | | submit.recommend |
| | | ? (submit.recommend = true) |
| | | : (submit.recommend = false); |
| | | if (this.goodsId) { |
| | | API_GOODS.editGoods(this.goodsId, submit).then((res) => { |
| | | if (res.success) { |
| | | this.submitLoading = false; |
| | | this.$router.go(-1); |
| | | } else { |
| | | this.submitLoading = false; |
| | | try { |
| | | this.submitLoading = true; |
| | | this.$refs["baseInfoForm"].validate((valid) => { |
| | | if (valid) { |
| | | if (this.baseInfoForm.salesModel === "WHOLESALE") { |
| | | for (let i = 0; i < this.wholesaleData.length; i++) { |
| | | this.checkWholesaleNum(i); |
| | | this.checkWholesalePrice(i); |
| | | this.wholesaleData[i].goodsId = this.goodsId; |
| | | } |
| | | this.baseInfoForm.wholesaleList = this.wholesaleData; |
| | | } |
| | | this.baseInfoForm.goodsId = this.goodsId; |
| | | let submit = JSON.parse(JSON.stringify(this.baseInfoForm)); |
| | | console.log('----------------->提交',submit); |
| | | if ( |
| | | submit.goodsGalleryFiles && |
| | | submit.goodsGalleryFiles.length <= 0 |
| | | ) { |
| | | this.submitLoading = false; |
| | | this.$Message.error("请上传商品图片"); |
| | | return; |
| | | } |
| | | if (!submit.goodsVideo){ |
| | | this.submitLoading = false; |
| | | this.$Message.error("请上传商品视频"); |
| | | return; |
| | | } |
| | | if (submit.templateId === "") submit.templateId = 0; |
| | | let flag = false; |
| | | let paramValue = ""; |
| | | |
| | | if (flag) { |
| | | this.$Message.error(paramValue + " 参数值不能为空"); |
| | | this.submitLoading = false; |
| | | return; |
| | | } |
| | | |
| | | if (this.goodsUnitList && !this.goodsUnitList.find(i => i === this.baseInfoForm.goodsUnit)) { |
| | | submit.goodsUnit = "" |
| | | this.$Message.error("商品单位不存在"); |
| | | this.submitLoading = false; |
| | | return; |
| | | } |
| | | let skuInfoNames = this.skuInfo.map((n) => n.name); |
| | | submit.skuList = []; |
| | | let containEmptyImage = false; |
| | | this.skuTableData.map((sku) => { |
| | | let skuCopy = { |
| | | cost: 1, |
| | | price: sku.price, |
| | | quantity: sku.quantity, |
| | | // alertQuantity: sku.alertQuantity, |
| | | sn: sku.sn, |
| | | images: [], |
| | | }; |
| | | if (this.openImage) { |
| | | this.skuInfo[0].spec_values.forEach(item => { |
| | | if (!item.images || item.images.length === 0) { |
| | | containEmptyImage = true; |
| | | return; |
| | | } |
| | | if (item.value === sku[this.skuInfo[0].name]) { |
| | | skuCopy.images = item.images |
| | | } |
| | | }) |
| | | |
| | | } |
| | | if (sku.weight) { |
| | | skuCopy.weight = sku.weight; |
| | | } |
| | | if (this.baseInfoForm.weight) { |
| | | skuCopy.weight = this.baseInfoForm.weight; |
| | | } |
| | | if (sku.id) { |
| | | skuCopy.id = sku.id; |
| | | } |
| | | for (let skuInfoName of skuInfoNames) { |
| | | skuCopy[skuInfoName] = sku[skuInfoName]; |
| | | } |
| | | submit.skuList.push(skuCopy); |
| | | }); |
| | | if (containEmptyImage) { |
| | | this.$Message.error("开启规格图片,所有规格图片不能为空!"); |
| | | this.submitLoading = false; |
| | | return; |
| | | } |
| | | if (submit.goodsGalleryFiles.length > 0) { |
| | | submit.goodsGalleryList = submit.goodsGalleryFiles.map( |
| | | (i) => i |
| | | ); |
| | | } |
| | | /** 参数校验 **/ |
| | | /* Object.keys(submit.goodsParamsList).forEach((item) => { |
| | | });*/ |
| | | submit.release ? (submit.release = true) : (submit.release = false); |
| | | submit.recommend |
| | | ? (submit.recommend = true) |
| | | : (submit.recommend = false); |
| | | if (this.goodsId) { |
| | | API_GOODS.editGoods(this.goodsId, submit).then((res) => { |
| | | if (res.success) { |
| | | this.submitLoading = false; |
| | | this.$router.go(-1); |
| | | } else { |
| | | this.submitLoading = false; |
| | | } |
| | | }); |
| | | } else { |
| | | API_GOODS.createGoods(submit).then((res) => { |
| | | if (res.success) { |
| | | this.submitLoading = false; |
| | | this.$parent.activestep = 2; |
| | | window.scrollTo(0, 0); |
| | | } else { |
| | | this.submitLoading = false; |
| | | } |
| | | }); |
| | | } |
| | | } else { |
| | | API_GOODS.createGoods(submit).then((res) => { |
| | | if (res.success) { |
| | | this.submitLoading = false; |
| | | this.$parent.activestep = 2; |
| | | window.scrollTo(0, 0); |
| | | } else { |
| | | this.submitLoading = false; |
| | | } |
| | | }); |
| | | } |
| | | } else { |
| | | this.submitLoading = false; |
| | | this.submitLoading = false; |
| | | |
| | | this.$Message.error("还有必填项未做处理,请检查表单"); |
| | | } |
| | | }); |
| | | this.$Message.error("还有必填项未做处理,请检查表单"); |
| | | } |
| | | }); |
| | | } finally { |
| | | this.submitLoading = false; |
| | | } |
| | | }, |
| | | /** 保存为模板 */ |
| | | saveToDraft() { |
| | |
| | | } else if (type === 'localRefresh') { |
| | | this.$Message.error("刷新失败,请重试"); |
| | | } |
| | | }).catch(reason => { |
| | | console.log("获取模板失败",reason) |
| | | }); |
| | | } |
| | | }, |
| | | removeVideo(){ |
| | | this.baseInfoForm.showGoodsVideo = null; |
| | | this.baseInfoForm.goodsVideo = null; |
| | | }, |
| | | // todo 文件上传 |
| | | async upLoadImg(file) { |
| | | console.log(file,this.count++); |
| | | if (this.listImages.length >= 5) { |
| | | this.$Message.error("图片上传不能超过5个"); |
| | | return; |
| | | } |
| | | try { |
| | | // this.upLoadVideoLoading = true; |
| | | // 获取文件上传临时密钥 |
| | | const sts = await getSts(); |
| | | const cos = new COS({ |
| | | getAuthorization: async function (options, callback) { |
| | | callback({ |
| | | TmpSecretId: sts.data.tmpSecretId, |
| | | TmpSecretKey: sts.data.tmpSecretKey, |
| | | SecurityToken: sts.data.sessionToken, |
| | | // 建议返回服务器时间作为签名的开始时间,避免客户端本地时间偏差过大导致签名错误 |
| | | StartTime: sts.data.stsStartTime, // 时间戳,单位秒,如:1580000000 |
| | | ExpiredTime: sts.data.stsEndTime,// 时间戳,单位秒,如:1580000000 |
| | | ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用 |
| | | }); |
| | | } |
| | | }) |
| | | const fileKey = getFileKey(file.name) |
| | | const upData = await cos.uploadFile({ |
| | | Bucket: sts.data.bucket, |
| | | Region: sts.data.region, |
| | | Key: fileKey, |
| | | Body: file, // 要上传的文件对象。 |
| | | SliceSize: 1024 * 1024 * 5, |
| | | onProgress: function (progressData) { |
| | | console.log('上传进度:', progressData); |
| | | }, |
| | | }); |
| | | console.log("上传成功", upData) |
| | | this.$nextTick(() => { |
| | | this.listImages.push(fileKey); |
| | | this.showListImages.push(sts.data.endpoint + "/" + fileKey); |
| | | this.baseInfoForm.goodsGalleryFiles.push(fileKey); |
| | | }) |
| | | |
| | | } catch (e) { |
| | | console.log("上传失败", upData) |
| | | return false; |
| | | } finally { |
| | | // this.upLoadVideoLoading = false; |
| | | |
| | | } |
| | | return false; |
| | | }, |
| | | async upLoadVideo(file) { |
| | | try { |
| | | // this.upLoadVideoLoading = true; |
| | | // 获取文件上传临时密钥 |
| | | const sts = await getSts(); |
| | | const cos = new COS({ |
| | | getAuthorization: async function (options, callback) { |
| | | callback({ |
| | | TmpSecretId: sts.data.tmpSecretId, |
| | | TmpSecretKey: sts.data.tmpSecretKey, |
| | | SecurityToken: sts.data.sessionToken, |
| | | // 建议返回服务器时间作为签名的开始时间,避免客户端本地时间偏差过大导致签名错误 |
| | | StartTime: sts.data.stsStartTime, // 时间戳,单位秒,如:1580000000 |
| | | ExpiredTime: sts.data.stsEndTime,// 时间戳,单位秒,如:1580000000 |
| | | ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用 |
| | | }); |
| | | } |
| | | }) |
| | | const fileKey = getFileKey(file.name) |
| | | const upData = await cos.uploadFile({ |
| | | Bucket: sts.data.bucket, |
| | | Region: sts.data.region, |
| | | Key: fileKey, |
| | | Body: file, // 要上传的文件对象。 |
| | | SliceSize: 1024 * 1024 * 5, |
| | | onProgress: function (progressData) { |
| | | console.log('上传进度:', progressData); |
| | | }, |
| | | }); |
| | | console.log("上传成功", upData) |
| | | this.$nextTick(() => { |
| | | this.baseInfoForm.goodsVideo = fileKey; |
| | | this.baseInfoForm.showGoodsVideo = sts.data.endpoint + "/" + fileKey; |
| | | this.baseInfoForm.goodsVideo = fileKey; |
| | | }) |
| | | |
| | | } catch (e) { |
| | | console.log("上传失败", upData) |
| | | return false; |
| | | } finally { |
| | | // this.upLoadVideoLoading = false; |
| | | |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.accessToken = { |
| | |
| | | this.baseInfoForm.goodsType = this.firstData.goodsType; |
| | | |
| | | |
| | | /** 获取该商城分类下 商品参数信息 */ |
| | | this.GET_GoodsParams(); |
| | | /** 查询品牌列表 */ |
| | | this.getGoodsBrandList(); |
| | | /** 查询分类绑定的规格信息 */ |
| | | this.Get_SkuInfoByCategory(this.categoryId); |
| | | |
| | | |
| | | if (this.categoryId!=null && this.categoryId!=='') { |
| | | /** 获取该商城分类下 商品参数信息 */ |
| | | this.GET_GoodsParams(); |
| | | console.log('分类id------------------>',this.categoryId); |
| | | /** 查询分类绑定的规格信息 */ |
| | | this.Get_SkuInfoByCategory(this.categoryId); |
| | | /** 查询品牌列表 */ |
| | | this.getGoodsBrandList(); |
| | | } |
| | | // 获取商品单位 |
| | | this.GET_GoodsUnit(); |
| | | // 获取当前店铺分类 |
| | |
| | | .refresh-icon { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .demo-upload-list { |
| | | display: inline-block; |
| | | width: 60px; |
| | | height: 60px; |
| | | text-align: center; |
| | | line-height: 60px; |
| | | border: 1px solid transparent; |
| | | border-radius: 4px; |
| | | overflow: hidden; |
| | | background: #fff; |
| | | position: relative; |
| | | box-shadow: 0 1px 1px rgba(0, 0, 0, .2); |
| | | margin-right: 4px; |
| | | } |
| | | |
| | | .demo-upload-list img { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .demo-upload-list-cover { |
| | | display: none; |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background: rgba(0, 0, 0, .6); |
| | | } |
| | | |
| | | .demo-upload-list:hover .demo-upload-list-cover { |
| | | display: block; |
| | | } |
| | | |
| | | .demo-upload-list-cover i { |
| | | color: #fff; |
| | | font-size: 20px; |
| | | cursor: pointer; |
| | | margin: 0 2px; |
| | | } |
| | | </style> |
| | |
| | | <!-- 使用 fullscreen 类来控制是否全屏显示 --> |
| | | <div :class="{ fullscreen: fullscreen }" class="tinymce-container"> |
| | | <!-- 使用 tinymce-textarea 类作为编辑器的文本区域 --> |
| | | <uploadImage @callback="insertImage" /> |
| | | <uploadImage @callback="insertImage" v-if="showUpload"/> |
| | | <textarea :id="tinymceId" class="tinymce-textarea" /> |
| | | </div> |
| | | </div> |
| | |
| | | height:{ |
| | | type:String, |
| | | default:'500px' |
| | | },showUpload:{ |
| | | type:Boolean, |
| | | default:true |
| | | } |
| | | }, |
| | | data() { |