Merge remote-tracking branch 'origin/dev' into dev
| | |
| | | "@antv/g2": "^4.1.12", |
| | | "axios": "^0.21.1", |
| | | "core-js": "^3.6.5", |
| | | "cos-js-sdk-v5": "^1.10.1", |
| | | "dplayer": "^1.26.0", |
| | | "js-cookie": "^2.2.1", |
| | | "node-sass": "^4.14.1", |
| | | "price-color": "1.0.2", |
| | | "sass-loader": "^8.0.2", |
| | | "sockjs-client": "^1.4.0", |
| | | "swiper": "^6.3.5", |
| | |
| | | "vue-router": "^3.1.3", |
| | | "vuedraggable": "^2.23.2", |
| | | "vuex": "^3.4.0", |
| | | "xss": "^1.0.7", |
| | | "price-color": "1.0.2" |
| | | "xss": "^1.0.7" |
| | | }, |
| | | "devDependencies": { |
| | | "@vue/cli-plugin-babel": "^4.4.4", |
| | |
| | | }) |
| | | } |
| | | |
| | | // 获取STS访问令牌 |
| | | export const getSts = () => { |
| | | return service({ |
| | | baseURL: commonUrl, |
| | | url: "/common/lmk/file/sts", |
| | | method: "GET" |
| | | }) |
| | | } |
| | | |
New file |
| | |
| | | import service from "@/libs/axios"; |
| | | |
| | | // 视频发布 |
| | | export const healthVideo = (data) => { |
| | | return service({ |
| | | url: "/lkm/health/healthVideo", |
| | | method: "POST", |
| | | data: data |
| | | }) |
| | | } |
| | | // 视频修改 |
| | | export const updateHealthVideo = (data) => { |
| | | return service({ |
| | | url: "/lkm/health/updateHealthVideo", |
| | | method: "POST", |
| | | data: data |
| | | }) |
| | | } |
| | | // 视频查询 |
| | | export const getHealthVideos = (data) => { |
| | | return service({ |
| | | url: "/lkm/health/page", |
| | | method: "POST", |
| | | data: data |
| | | }) |
| | | } |
| | | // 视频查询 |
| | | export const delHealth = (id) => { |
| | | return service({ |
| | | url: "/lkm/health/del/" + id, |
| | | method: "POST" |
| | | }) |
| | | } |
New file |
| | |
| | | import service from "@/libs/axios"; |
| | | |
| | | // 厨神视频发布 |
| | | export const addKitchenVideo = (data) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-video/addKitchenVideo", |
| | | method: "POST", |
| | | data: data |
| | | }) |
| | | } |
| | | // 视频修改 |
| | | export const updateKitchenVideo = (data) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-video/updateKitchenVideo", |
| | | method: "POST", |
| | | data: data |
| | | }) |
| | | } |
| | | // 视频查询 |
| | | export const getKitchenVideos = (data) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-video/page", |
| | | method: "POST", |
| | | data: data |
| | | }) |
| | | } |
| | | // 删除视频 |
| | | export const delKitchen = (id) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-video/del/" + id, |
| | | method: "POST" |
| | | }) |
| | | } |
New file |
| | |
| | | import service from "@/libs/axios"; |
| | | |
| | | // 神厨分页 |
| | | export const getKitchenType = (data) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-type/page", |
| | | method: "GET", |
| | | params: data |
| | | }) |
| | | } |
| | | // 神厨分类不分页 |
| | | export const getKitchenTypeAllList = () => { |
| | | return service({ |
| | | url: "/lmk/kitchen-type/list", |
| | | method: "GET", |
| | | }) |
| | | } |
| | | // 添加神厨标签 |
| | | export const addKitchenType = (data) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-type", |
| | | method: "POST", |
| | | data: data |
| | | }) |
| | | } |
| | | // 添加神厨标签 |
| | | export const editKitchenType = (data) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-type", |
| | | method: "PUT", |
| | | data: data |
| | | }) |
| | | } |
| | | // 删除神厨标签 |
| | | export const delKitchenType = (id) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-type/"+id, |
| | | method: "DELETE", |
| | | }) |
| | | } |
| | | // 批量删除神厨标签 |
| | | export const deleteBatch = (data) => { |
| | | return service({ |
| | | url: "/lmk/kitchen-type/batch", |
| | | method: "DELETE", |
| | | data: data |
| | | }) |
| | | } |
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: 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({ |
New file |
| | |
| | | <template> |
| | | <div> |
| | | <Card> |
| | | <Form |
| | | ref="searchForm" |
| | | @keydown.enter.native="handleSearch" |
| | | :model="searchForm" |
| | | inline |
| | | :label-width="70" |
| | | class="search-form" |
| | | > |
| | | <Form-item label="标题" prop="title"> |
| | | <Input |
| | | type="text" |
| | | v-model="searchForm.title" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | style="width: 160px" |
| | | /> |
| | | </Form-item> |
| | | <!-- todo 暂时隐藏大健康一期没定义标签--> |
| | | <Form-item v-if="false" label="标签" prop="tagList"> |
| | | <Select |
| | | v-model="searchForm.tagList" |
| | | clearable |
| | | filterable |
| | | multiple |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | style="width: 160px" |
| | | > |
| | | <Option v-for="tag in tagList" :key="tag.id" :value="tag.id">{{ tag.tagName }}</Option> |
| | | </Select> |
| | | </Form-item> |
| | | <Form-item label="视频状态" prop="status"> |
| | | <Select |
| | | v-model="searchForm.status" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | style="width: 160px" |
| | | > |
| | | <Option value="99">待审核</Option> |
| | | <Option value="1">已发布</Option> |
| | | <Option value="0">已下架</Option> |
| | | <Option value="-1">审核未通过</Option> |
| | | </Select> |
| | | </Form-item> |
| | | <Button |
| | | @click="handleSearch" |
| | | type="primary" |
| | | icon="ios-search" |
| | | class="search-btn" |
| | | >搜索 |
| | | </Button |
| | | > |
| | | <Button |
| | | @click="handleVideoUpLoad" |
| | | type="primary" |
| | | icon="md-arrow-up" |
| | | class="search-btn" |
| | | >上传视频 |
| | | </Button |
| | | > |
| | | </Form> |
| | | <!-- 大健康视频上传--> |
| | | <Modal |
| | | v-model="upLoadVideoShow" |
| | | :title="uploadVideoForm.id?'编辑大健康视频':'上传大健康视频'" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | |
| | | <Form |
| | | :model="uploadVideoForm" |
| | | ref="uploadVideoForm" |
| | | :rules="uploadVideoFileRule" |
| | | > |
| | | <Row :gutter="24"> |
| | | <Col span="24"> |
| | | <Spin size="large" fix v-if="upLoadVideoLoading"> 文件上传中...</Spin> |
| | | </Col> |
| | | <Col span="12"> |
| | | <FormItem label="标题" prop="title"> |
| | | <Input placeholder="请输入标题" v-model="uploadVideoForm.title" |
| | | style="width: 200px" |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24"> |
| | | <FormItem label="刷新dom使用" prop="title" v-show="false"> |
| | | <Input placeholder="请输入标题" v-model="uploadVideoForm.temp" |
| | | style="width: 200px" |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="12" v-if="!uploadVideoForm.videoFileKey"> |
| | | <FormItem label="上传视频" prop="videoFileKey"> |
| | | <Upload |
| | | :multiple="true" |
| | | :before-upload="upLoadVideo" |
| | | accept="video/*" |
| | | action="" |
| | | > |
| | | <Button icon="ios-cloud-upload-outline">选择视频</Button> |
| | | </Upload> |
| | | </FormItem> |
| | | </Col> |
| | | |
| | | <Col span="24" v-else> |
| | | <FormItem label="视频"> |
| | | <video style="width: 150px;height: 150px" |
| | | controls |
| | | @loadedmetadata="getVideoDuration" |
| | | :poster="uploadVideoForm.showCoverUrl" |
| | | :autoplay="false" |
| | | id="remoteVideo" :src="uploadVideoForm.showVideoUrl" |
| | | ref="healthVideoInfo" |
| | | ></video> |
| | | </FormItem> |
| | | </Col> |
| | | |
| | | <Col span="12" v-show="uploadVideoForm.videoFileKey && !uploadVideoForm.coverUrl"> |
| | | <FormItem label="上传封面" prop="coverUrl"> |
| | | <Upload |
| | | :multiple="true" |
| | | :before-upload="upLoadImg" |
| | | accept="image/*" |
| | | action="" |
| | | > |
| | | <Button icon="ios-cloud-upload-outline">选择封面</Button> |
| | | </Upload> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24"> |
| | | <div> |
| | | <Button type="primary" @click="clearCoverImage" v-show="uploadVideoForm.coverUrl">重新上传封面</Button> |
| | | <Button type="primary" @click="clearVideo" style="margin-left: 20px" |
| | | v-show="uploadVideoForm.videoFileKey">重新上传视频 |
| | | </Button> |
| | | </div> |
| | | </Col> |
| | | <!-- <Col span="24" v-else>--> |
| | | <!-- <FormItem label="封面">--> |
| | | <!-- <div class="showCoverImg" style="width: 150px;height: 150px;">--> |
| | | <!-- <img :src="uploadVideoForm.showCoverUrl" style="width: 150px;height: 150px" class="coverImg"/>--> |
| | | <!-- <Icon type="ios-close" size="24" class="coverImgRemove" color="red"--> |
| | | <!-- style="border-radius: 50%;background: #fff;cursor: pointer"--> |
| | | <!-- @click="removeCover"--> |
| | | <!-- />--> |
| | | <!-- </div>--> |
| | | <!-- </FormItem>--> |
| | | <!-- </Col>--> |
| | | </Row> |
| | | |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="closeHealthVideo">关闭</Button> |
| | | <Button type="primary" @click="submitHealthVideo">确认</Button> |
| | | </div> |
| | | </Modal> |
| | | <Modal |
| | | v-model="playVideoShow" |
| | | :title="playVideoTitle" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <div class="video-warp"> |
| | | <video :src="playVideoUrl" autoplay controls style="width: 768px;height: 432px"/> |
| | | </div> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="playVideoClose">关闭</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | <Modal |
| | | v-model="auditingShow" |
| | | title="视频审核" |
| | | width="800" |
| | | :loading="auditingLoading" |
| | | :mask-closable="false" |
| | | > |
| | | |
| | | <Form |
| | | ref="auditingForm" |
| | | :model="auditingForm" |
| | | :label-width="70" |
| | | :rules="auditingRule" |
| | | > |
| | | <Form-item label="标题:"> |
| | | <div>{{ detail.title }}</div> |
| | | </Form-item> |
| | | <Form-item label="标签:"> |
| | | <div style="display: flex;flex-wrap: wrap"> |
| | | <div v-for="(tag, index) in detail.tagList" :key="'tag' + index" style="margin-right: 5px"> |
| | | <Tag color="red">{{ tag.tagName }}</Tag> |
| | | </div> |
| | | </div> |
| | | </Form-item> |
| | | <Form-item label="视频时长:" :label-width="72"> |
| | | <div>{{ formatSeconds(detail.videoDuration) }}</div> |
| | | </Form-item> |
| | | <Form-item class="video-warp" :label-width="0"> |
| | | <video :src="detail.videoUrl" autoplay controls style="width: 768px;height: 432px"/> |
| | | </Form-item> |
| | | <Form-item label="审核结果:" :label-width="100" prop="result"> |
| | | <RadioGroup v-model="auditingForm.result"> |
| | | <Radio :label="1">通过</Radio> |
| | | <Radio :label="0">不通过</Radio> |
| | | </RadioGroup> |
| | | </Form-item> |
| | | <Form-item v-show="auditingForm.result === 0" label="不通过原因:" :label-width="100" prop="reason"> |
| | | <Input |
| | | type="textarea" |
| | | v-model="auditingForm.reason" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </Form-item> |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="closeAuditing">关闭</Button> |
| | | <Button type="primary" @click="submitAuditing">确认</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | <Modal |
| | | v-model="videoDownShow" |
| | | title="视频下架" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <Form :model="videoDownForm" :rules="videoDownRule" ref="videoDownForm"> |
| | | <FormItem label="下架原因:" :labelWidth="100" prop="reason"> |
| | | <editor ref="editor" @input="getReason"/> |
| | | </FormItem> |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="closeVideoDown">关闭</Button> |
| | | <Button type="primary" @click="videoDown">确认</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | <Table |
| | | :loading="loading" |
| | | border |
| | | :columns="columns" |
| | | :data="data" |
| | | ref="table" |
| | | sortable="custom" |
| | | @on-sort-change="changeSort" |
| | | @on-selection-change="showSelect" |
| | | > |
| | | <template slot-scope="{ row, index }" slot="tagList"> |
| | | <div v-for="(tag, index) in row.tagList" :key="'tag' + index" style="margin-top: 5px"> |
| | | <Tag color="red">{{ tag.tagName }}</Tag> |
| | | </div> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="videoFileKey"> |
| | | <div class="play-text" @click="playVideo(row.videoFileKey, row.title)">点击播放</div> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="videoDuration"> |
| | | <div>{{ formatSeconds(row.videoDuration) }}</div> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="recommend"> |
| | | <i-switch v-model="row.recommend" :before-change="() => handleBeforeChange(row)" true-color="#13ce66"/> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="status"> |
| | | {{ transStatus(row.status) }} |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="action"> |
| | | <Button type="primary" size="small" style="margin-right: 5px" v-if="row.status === '99'" |
| | | @click="openAuditing(row)">审核 |
| | | </Button> |
| | | <Button type="error" size="small" style="margin-right: 5px" v-if="row.status === '1'" |
| | | @click="openVideoDown(row)">下架 |
| | | </Button> |
| | | <Button type="success" size="small" style="margin-right: 5px" v-else-if="row.status === '0'" |
| | | @click="videoUp(row)">上架 |
| | | </Button> |
| | | <Button type="success" size="small" style="margin-right: 5px" |
| | | @click="handleVideoUpLoad(row)">编辑 |
| | | </Button> |
| | | <Button type="success" size="small" style="margin-right: 5px" |
| | | @click="deleteHealthVideo(row)">删除 |
| | | </Button> |
| | | </template> |
| | | </Table> |
| | | |
| | | <Row type="flex" justify="end" class="mt_10"> |
| | | <Page |
| | | :current="searchForm.pageNumber" |
| | | :total="total" |
| | | :page-size="searchForm.pageSize" |
| | | @on-change="changePage" |
| | | @on-page-size-change="changePageSize" |
| | | :page-size-opts="[10, 20, 50]" |
| | | size="small" |
| | | show-total |
| | | show-elevator |
| | | show-sizer |
| | | ></Page> |
| | | </Row> |
| | | </Card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import {recommendSet, getVideoById, auditingVideo, up, down} from "@/api/video"; |
| | | import {healthVideo, getHealthVideos, updateHealthVideo,delHealth} from "@/api/health-video"; |
| | | import {getVideoTagList} from "@/api/videoTag"; |
| | | import {getFilePreview, getSts} from "@/api/file"; |
| | | import Editor from '@/components/editor/index.vue' |
| | | import COS from 'cos-js-sdk-v5'; |
| | | import {getFileKey} from "@/utils/file.js"; |
| | | |
| | | export default { |
| | | name: "VideoList", |
| | | components: {Editor}, |
| | | data() { |
| | | return { |
| | | videoDownForm: { |
| | | id: '', |
| | | reason: '' |
| | | }, |
| | | videoDownRule: { |
| | | reason: [ |
| | | { |
| | | require: true, |
| | | message: '请输入下架原因', |
| | | trigger: 'blur', |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === '') { |
| | | callback(new Error('请输入下架原因')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | videoDownShow: false, // 视频下架 |
| | | videoDownMsg: '', // 下架提示信息 |
| | | auditingForm: { // 审核表单 |
| | | id: null, |
| | | result: null, |
| | | reason: '' |
| | | }, |
| | | auditingRule: { |
| | | result: [ |
| | | { |
| | | required: true, |
| | | message: '请选择视频审核结果', |
| | | trigger: 'change', |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined) { |
| | | callback(new Error('请选择视频审核结果')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | }, |
| | | uploadVideoFileRule: { |
| | | coverUrl: [ |
| | | { |
| | | required: true, |
| | | message: '请上传封面', |
| | | trigger: 'blur', |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined) { |
| | | callback(new Error('请上传封面')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | title: [ |
| | | { |
| | | required: true, |
| | | message: '请输入标题', |
| | | trigger: 'blur', |
| | | validator: (rule, value, callback) => { |
| | | console.log('验证值:-------------->', value, '类型:', typeof value); |
| | | if (value === null || value === undefined) { |
| | | callback(new Error('请输入标题')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | }, |
| | | detail: {}, // 视频详情信息 |
| | | auditingShow: false, // 审核弹窗 |
| | | upLoadVideoShow: false,//文件上传弹窗 |
| | | auditingLoading: false, // 审核弹窗 |
| | | upLoadVideoLoading: false,//上传视频 |
| | | playVideoShow: false, // 视频播放弹窗 |
| | | playVideoTitle: '', // 视频播放标题 |
| | | playVideoUrl: '', // 当前正在播放的视频地址 |
| | | modelShow: false, // 弹窗显隐 |
| | | modelTitle: '', // 弹窗title |
| | | loading: false, // 表单加载状态 |
| | | searchForm: { |
| | | // 搜索框初始化对象 |
| | | pageNumber: 1, // 当前页数 |
| | | pageSize: 10, // 页面大小 |
| | | title: '', // 标题 |
| | | tagList: [], // 标签 |
| | | status: '99' |
| | | }, |
| | | tagList: [], // 标签列表 |
| | | columns: [ |
| | | { |
| | | type: 'selection', |
| | | width: 60, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "标题", |
| | | key: "title", |
| | | minWidth: 240, |
| | | tooltip: true, |
| | | }, |
| | | // { |
| | | // title: "作者", |
| | | // key: "authorName", |
| | | // width: 130, |
| | | // tooltip: true, |
| | | // }, |
| | | // { |
| | | // title: "视频标签", |
| | | // key: "tagList", |
| | | // width: 180, |
| | | // slot: "tagList", |
| | | // }, |
| | | { |
| | | title: "视频内容", |
| | | key: "videoFileKey", |
| | | width: 170, |
| | | slot: "videoFileKey" |
| | | }, |
| | | { |
| | | title: "时长", |
| | | key: "videoDuration", |
| | | width: 80, |
| | | align: 'center', |
| | | slot: "videoDuration", |
| | | }, |
| | | { |
| | | title: "播放量", |
| | | key: "playNum", |
| | | width: 80, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "收藏数", |
| | | key: "collectNum", |
| | | width: 80, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "评论数", |
| | | key: "commentNum", |
| | | width: 80, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "首页推荐", |
| | | key: "recommend", |
| | | slot: "recommend", |
| | | width: 100, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "权重", |
| | | key: "weight", |
| | | width: 170, |
| | | }, |
| | | { |
| | | title: "状态", |
| | | key: "status", |
| | | slot: "status", |
| | | width: 120, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "操作", |
| | | key: "action", |
| | | slot: "action", |
| | | align: "center", |
| | | width: 200, |
| | | }, |
| | | ], |
| | | data: [], // 表单数据 |
| | | total: 0, // 表单数据总数 |
| | | selectCount: 0, // 已选数量 |
| | | selectList: [], // 已选数据列表 |
| | | uploadVideoForm: { |
| | | id: null, |
| | | coverUrl: null, |
| | | videoFileKey: null, |
| | | videoFit: null, |
| | | videoDuration: null, |
| | | title: null, |
| | | videoContentType: null, |
| | | videoType: null, |
| | | showCoverUrl: null, |
| | | showVideoUrl: null, |
| | | temp: null |
| | | |
| | | }, |
| | | } |
| | | }, |
| | | created() { |
| | | this.getDataList(); |
| | | this.getTags('') |
| | | }, |
| | | methods: { |
| | | // 秒转x分x秒 |
| | | formatSeconds(seconds) { |
| | | if (isNaN(seconds) || seconds < 0) return '0秒'; |
| | | |
| | | const mins = Math.floor(seconds / 60); |
| | | const secs = seconds % 60; |
| | | |
| | | if (mins === 0) return `${secs}秒`; |
| | | if (secs === 0) return `${mins}分`; |
| | | |
| | | return `${mins}分${secs}秒`; |
| | | }, |
| | | // 获取标签列表 |
| | | getTags(tagName) { |
| | | let params = { |
| | | 'tagName': tagName |
| | | } |
| | | getVideoTagList(params).then(res => { |
| | | this.tagList = res.data |
| | | }) |
| | | }, |
| | | // 获取富文本编辑器的内容 |
| | | getReason(content) { |
| | | this.videoDownForm.reason = content |
| | | }, |
| | | //重新上传封面 |
| | | clearCoverImage() { |
| | | this.$set(this.uploadVideoForm, 'coverUrl', ''); |
| | | this.$set(this.uploadVideoForm, 'showCoverUrl', ''); |
| | | this.$set(this.uploadVideoForm, 'temp', new Date().getTime()); |
| | | }, |
| | | //重新上传视频 |
| | | clearVideo() { |
| | | this.clearCoverImage(); |
| | | this.$set(this.uploadVideoForm, 'videoFileKey', ''); |
| | | this.$set(this.uploadVideoForm, 'showVideoUrl', ''); |
| | | this.$set(this.uploadVideoForm, 'temp', new Date().getTime()); |
| | | console.log(this.uploadVideoForm) |
| | | }, |
| | | // 视频上架 |
| | | videoUp(row) { |
| | | this.$Modal.confirm({ |
| | | title: "操作确认", |
| | | content: "您确认要上架视频【 " + row.title + "】吗?", |
| | | loading: true, |
| | | onOk: () => { |
| | | up(row.id).then(res => { |
| | | this.$Modal.remove(); |
| | | if (res.code == 200) { |
| | | this.$Message.success("视频上架成功"); |
| | | this.getDataList(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // 视频下架 |
| | | videoDown() { |
| | | this.$refs.videoDownForm.validate((valid) => { |
| | | if (valid) { |
| | | down(this.videoDownForm).then(res => { |
| | | this.$Message.success("下架成功") |
| | | this.closeVideoDown() |
| | | this.getDataList() |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | // 关闭视频下架 |
| | | closeVideoDown() { |
| | | this.videoDownShow = false |
| | | this.videoDownForm = { |
| | | id: '', |
| | | reason: '' |
| | | } |
| | | this.$refs.editor.setContent('') |
| | | }, |
| | | // 视频下架 |
| | | openVideoDown(row) { |
| | | this.videoDownForm.id = row.id |
| | | this.videoDownShow = true |
| | | }, |
| | | // 视频发布/修改 |
| | | submitHealthVideo() { |
| | | try { |
| | | this.upLoadVideoLoading = true |
| | | this.$refs.uploadVideoForm.validate((valid) => { |
| | | if (valid) { |
| | | // 修改 |
| | | if (this.uploadVideoForm.id) { |
| | | updateHealthVideo(this.uploadVideoForm).then(res => { |
| | | this.$Message.success("修改完成") |
| | | this.closeHealthVideo() |
| | | this.getDataList() |
| | | }) |
| | | } else { |
| | | healthVideo(this.uploadVideoForm).then(res => { |
| | | this.$Message.success("添加完成") |
| | | this.closeHealthVideo() |
| | | this.getDataList() |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } finally { |
| | | this.upLoadVideoLoading = false |
| | | } |
| | | }, |
| | | // 关闭窗口 |
| | | closeHealthVideo() { |
| | | // |
| | | this.uploadVideoForm = {}; |
| | | this.upLoadVideoShow = false; |
| | | }, |
| | | // 提交审核结果 |
| | | submitAuditing() { |
| | | console.log(this.auditingForm, "sb") |
| | | this.$refs.auditingForm.validate((valid) => { |
| | | if (valid) { |
| | | auditingVideo(this.auditingForm).then(res => { |
| | | this.$Message.success("审核完成") |
| | | this.closeAuditing() |
| | | this.getDataList() |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | // 审核结果变化 |
| | | resultChange(selected) { |
| | | this.auditingForm.result = selected === '通过' ? 1 : 0 |
| | | console.log(this.auditingForm.result) |
| | | }, |
| | | closeAuditing() { |
| | | this.auditingForm = { |
| | | id: null, |
| | | result: null, |
| | | reason: '' |
| | | } |
| | | this.detail = {} |
| | | this.auditingShow = false |
| | | }, |
| | | // 打开审核弹窗 |
| | | openAuditing(row) { |
| | | this.auditingShow = true |
| | | this.auditingLoading = true |
| | | this.auditingForm.id = row.id |
| | | getVideoById(row.id).then(res => { |
| | | this.detail = res.data |
| | | this.auditingLoading = false |
| | | }) |
| | | }, |
| | | getVideoDuration(e){ |
| | | const duration = this.$refs.healthVideoInfo.duration; |
| | | this.uploadVideoForm.videoDuration = Math.floor(duration); |
| | | }, |
| | | // 打开编辑弹窗 |
| | | deleteHealthVideo(row) { |
| | | console.log('删除测试', row) |
| | | this.$Modal.confirm({ |
| | | title: "操作确认", |
| | | content: "您确认要删除视频【 " + row.title + "】吗?", |
| | | loading: true, |
| | | onOk: () => { |
| | | delHealth(row.id).then(res => { |
| | | this.$Modal.remove(); |
| | | if (res.code === 200) { |
| | | this.$Message.success("视频删除成功"); |
| | | this.getDataList(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // 翻译状态 |
| | | transStatus(status) { |
| | | switch (status) { |
| | | case '99': |
| | | return '待审核' |
| | | case '1': |
| | | return '已发布' |
| | | case '0': |
| | | return '已下架' |
| | | case '-1': |
| | | return '审核未通过' |
| | | default: |
| | | return '未知' |
| | | } |
| | | }, |
| | | // 开启或关闭推荐的方法 |
| | | handleBeforeChange(row) { |
| | | let content = "" |
| | | if (row.recommend) { |
| | | content = '确认要关闭首页推荐吗?' |
| | | } else { |
| | | content = '确认要开启首页推荐吗?' |
| | | } |
| | | return new Promise((resolve) => { |
| | | this.$Modal.confirm({ |
| | | title: '操作提醒', |
| | | content: content, |
| | | onOk: () => { |
| | | recommendSet({id: row.id, recommend: !row.recommend}).then(res => { |
| | | this.$Message.success(res.msg); |
| | | resolve(); |
| | | }) |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | // 关闭视频播放 |
| | | playVideoClose() { |
| | | this.playVideoTitle = ''; |
| | | this.playVideoUrl = ''; |
| | | this.playVideoShow = false |
| | | }, |
| | | // 点击播放视频 |
| | | playVideo(fileKey, title) { |
| | | this.playVideoTitle = title; |
| | | |
| | | getFilePreview(fileKey).then(res => { |
| | | this.playVideoUrl = res.data |
| | | this.playVideoShow = true |
| | | }) |
| | | }, |
| | | // 搜索 |
| | | handleSearch() { |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = 10; |
| | | this.getDataList(); |
| | | }, |
| | | // 获取列表数据 |
| | | getDataList() { |
| | | this.loading = true; |
| | | getHealthVideos(this.searchForm).then((res) => { |
| | | console.log(res) |
| | | this.loading = false; |
| | | if (res.code === 200) { |
| | | this.data = res.data; |
| | | this.total = res.total; |
| | | } |
| | | }); |
| | | this.total = this.data.length; |
| | | this.loading = false; |
| | | }, |
| | | showSelect(e) { |
| | | this.selectList = e.map(d => d.id); |
| | | this.selectCount = e.length; |
| | | }, |
| | | // 排序 |
| | | changeSort(e) { |
| | | this.searchForm.sort = e.key; |
| | | this.searchForm.order = e.order; |
| | | if (e.order == "normal") { |
| | | this.searchForm.order = ""; |
| | | } |
| | | this.getDataList(); |
| | | }, |
| | | // 分页 改变页码 |
| | | changePage(v) { |
| | | this.searchForm.pageNumber = v; |
| | | this.getDataList(); |
| | | }, |
| | | // 分页 改变页数 |
| | | changePageSize(v) { |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = v; |
| | | this.getDataList(); |
| | | }, |
| | | handleVideoUpLoad(row) { |
| | | this.uploadVideoForm = {}; |
| | | this.upLoadVideoShow = true; |
| | | if (row.id) { |
| | | this.uploadVideoForm.id = row.id; |
| | | this.uploadVideoForm.showVideoUrl = row.videoUrl |
| | | this.uploadVideoForm.videoFileKey = row.videoFileKey; |
| | | this.uploadVideoForm.coverUrl = row.coverUrl; |
| | | this.uploadVideoForm.showCoverUrl = row.coverShowUrl; |
| | | this.uploadVideoForm.title = row.title; |
| | | } |
| | | }, |
| | | async upLoadVideo(file) { |
| | | try { |
| | | this.$nextTick(() => { |
| | | 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(this.uploadVideoForm) |
| | | this.$nextTick(() => { |
| | | this.uploadVideoForm.videoFileKey = fileKey; |
| | | this.uploadVideoForm.showVideoUrl = sts.data.endpoint + "/" + fileKey; |
| | | }) |
| | | console.log("上传成功", upData) |
| | | const duration = this.$refs.healthVideoInfo.duration; |
| | | console.log('-测试获取时间信息---------------->', duration); |
| | | } catch (e) { |
| | | console.log("上传失败", upData) |
| | | } finally { |
| | | this.$nextTick(() => { |
| | | this.upLoadVideoLoading = false; |
| | | }) |
| | | } |
| | | return false; |
| | | }, |
| | | async upLoadImg(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.uploadVideoForm.coverUrl = fileKey; |
| | | this.uploadVideoForm.showCoverUrl = sts.data.endpoint + "/" + fileKey; |
| | | }) |
| | | |
| | | } catch (e) { |
| | | console.log("上传失败", upData) |
| | | } finally { |
| | | this.upLoadVideoLoading = false; |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .play-text { |
| | | width: 100%; |
| | | text-align: center; |
| | | color: #2d8cf0; |
| | | } |
| | | |
| | | .play-text:hover { |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .video-warp { |
| | | width: 786px; |
| | | height: 432px; |
| | | } |
| | | |
| | | .data-item { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .showCoverImg { |
| | | position: relative; |
| | | } |
| | | |
| | | .coverImgRemove { |
| | | position: absolute; |
| | | top: 15px; |
| | | right: -15px; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div> |
| | | <Card> |
| | | <Form |
| | | ref="searchForm" |
| | | @keydown.enter.native="handleSearch" |
| | | :model="searchForm" |
| | | inline |
| | | :label-width="70" |
| | | class="search-form" |
| | | > |
| | | <Form-item label="标签名称" prop="typeName"> |
| | | <Input |
| | | type="text" |
| | | v-model="searchForm.typeName" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | style="width: 160px" |
| | | /> |
| | | </Form-item> |
| | | <Button |
| | | @click="handleSearch" |
| | | type="primary" |
| | | icon="ios-search" |
| | | class="search-btn" |
| | | >搜索</Button |
| | | > |
| | | </Form> |
| | | |
| | | <Row class="operation padding-row"> |
| | | <Button @click="openAdd" type="info">添加</Button> |
| | | <Button @click="delBatch" type="error">批量删除</Button> |
| | | </Row> |
| | | |
| | | <Modal |
| | | v-model="modelShow" |
| | | :title="modelTitle" |
| | | > |
| | | <Form ref="form" :model="form" :label-width="70" :rules="rules"> |
| | | <Row :gutter="24"> |
| | | <Col span="12"> |
| | | <FormItem label="标签名称" prop="typeName"> |
| | | <Input v-model="form.typeName" autocomplete="off"/> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="12"> |
| | | <FormItem label="排序" prop="sortNum"> |
| | | <Input v-model="form.sortNum" autocomplete="off"/> |
| | | </FormItem> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="modelClose">取消</Button> |
| | | <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">提交</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | <Table |
| | | :loading="loading" |
| | | border |
| | | :columns="columns" |
| | | :data="data" |
| | | ref="table" |
| | | sortable="custom" |
| | | @on-sort-change="changeSort" |
| | | @on-selection-change="showSelect" |
| | | > |
| | | <template slot-scope="{ row, index }" slot="action"> |
| | | <Button type="info" size="small" style="margin-right: 5px" @click="openEdit(row)">编辑</Button> |
| | | <Button type="error" size="small" @click="delById(row)">删除</Button> |
| | | </template> |
| | | </Table> |
| | | |
| | | <Row type="flex" justify="end" class="mt_10"> |
| | | <Page |
| | | :current="searchForm.pageNumber" |
| | | :total="total" |
| | | :page-size="searchForm.pageSize" |
| | | @on-change="changePage" |
| | | @on-page-size-change="changePageSize" |
| | | :page-size-opts="[10, 20, 50]" |
| | | size="small" |
| | | show-total |
| | | show-elevator |
| | | show-sizer |
| | | ></Page> |
| | | </Row> |
| | | </Card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import JsonExcel from "vue-json-excel"; |
| | | import {deleteVideoTagById, getVideoTags, editVideoTag, addVideoTag, deleteVideoTagByIds} from "@/api/videoTag"; |
| | | import {addKitchenType, deleteBatch, delKitchenType, editKitchenType, getKitchenType} from "@/api/kitchen"; |
| | | export default { |
| | | name: "VideoTagList", |
| | | components: { |
| | | "download-excel": JsonExcel, |
| | | }, |
| | | data() { |
| | | return { |
| | | // 保存加载 |
| | | submitLoading: false, |
| | | // 新增修改表单 |
| | | form: { |
| | | id: '', |
| | | typeName: '', |
| | | sortNum: '', |
| | | }, |
| | | rules: { |
| | | typeName: [ |
| | | {required: true, message: "标签名称不能为空", trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === '') { |
| | | callback(new Error('标签名称不能为空')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | sortNum : [ |
| | | {required: true, message: "序号不能为空", trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === '') { |
| | | callback(new Error('序号不能为空')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }} |
| | | ], |
| | | }, |
| | | modelShow: false, // 弹窗显隐 |
| | | modelTitle: '', // 弹窗title |
| | | // 表格的表头以及内容 |
| | | fields: { |
| | | 类型: "tagName", |
| | | 引用次数: "useNum", |
| | | 排序: "sort_num", |
| | | 操作: "action" |
| | | }, |
| | | loading: true, // 表单加载状态 |
| | | searchForm: { |
| | | // 搜索框初始化对象 |
| | | pageNumber: 1, // 当前页数 |
| | | pageSize: 10, // 页面大小 |
| | | typeName: '', // 标签名称 |
| | | }, |
| | | selectDate: null, |
| | | columns: [ |
| | | { |
| | | type: 'selection', |
| | | width: 60, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "标签", |
| | | key: "typeName", |
| | | minWidth: 170, |
| | | tooltip: true, |
| | | }, |
| | | // { |
| | | // title: "引用次数", |
| | | // key: "useNum", |
| | | // width: 170, |
| | | // sortable: true |
| | | // }, |
| | | { |
| | | title: "排序", |
| | | key: "sortNum", |
| | | width: 400, |
| | | }, |
| | | { |
| | | title: "操作", |
| | | key: "action", |
| | | slot: "action", |
| | | align: "center", |
| | | width: 400, |
| | | }, |
| | | ], |
| | | data: [], // 表单数据 |
| | | total: 0, // 表单数据总数 |
| | | selectCount: 0, // 已选数量 |
| | | selectList: [], // 已选数据列表 |
| | | }; |
| | | }, |
| | | methods: { |
| | | showSelect(e) { |
| | | this.selectList = e.map(d => d.id); |
| | | this.selectCount = e.length; |
| | | }, |
| | | // 排序 |
| | | changeSort(e) { |
| | | this.searchForm.sort = e.key; |
| | | this.searchForm.order = e.order; |
| | | if (e.order == "normal") { |
| | | this.searchForm.order = ""; |
| | | } |
| | | this.getDataList(); |
| | | }, |
| | | // 批量删除 |
| | | delBatch() { |
| | | if (this.selectCount <= 0) { |
| | | this.$Message.warning("您还未选择要删除的数据"); |
| | | return; |
| | | } |
| | | this.$Modal.confirm({ |
| | | title: "确认删除", |
| | | content: "您确认要删除所选的 " + this.selectCount + " 条数据?", |
| | | loading: true, |
| | | onOk: () => { |
| | | deleteBatch(this.selectList).then(res => { |
| | | this.$Modal.remove(); |
| | | if (res.code == 200) { |
| | | this.$Message.success("删除成功"); |
| | | this.selectList = []; |
| | | this.selectCount = 0; |
| | | this.getDataList(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // id删除 |
| | | delById(row) { |
| | | this.$Modal.confirm({ |
| | | title: "确认删除", |
| | | content: "您确认要删除标签: " + row.typeName + " ?", |
| | | loading: true, |
| | | onOk: () => { |
| | | delKitchenType(row.id).then(res => { |
| | | this.$Modal.remove(); |
| | | if (res.code == 200) { |
| | | this.$Message.success("删除成功"); |
| | | this.getDataList(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // 打开新增 |
| | | openAdd() { |
| | | this.modelTitle = "新增标签" |
| | | this.modelShow = true |
| | | this.form ={} |
| | | }, |
| | | // 打开修改 |
| | | openEdit(row) { |
| | | this.modelTitle = "修改标签" |
| | | this.form = {}; |
| | | this.form.id = row.id |
| | | this.form.typeName = row.typeName |
| | | this.form.sortNum = row.sortNum |
| | | this.modelShow = true |
| | | console.log(this.form) |
| | | }, |
| | | // 新增或修改 |
| | | saveOrUpdate() { |
| | | this.$refs.form.validate(valid => { |
| | | try { |
| | | if (valid) { |
| | | this.submitLoading = true |
| | | if (this.form.id) { |
| | | // 修改 |
| | | editKitchenType(this.form).then(res => { |
| | | if (res.code == 200) { |
| | | this.$Message.success("修改成功"); |
| | | this.modelClose() |
| | | this.getDataList() |
| | | } |
| | | }) |
| | | } else { |
| | | // 新增 |
| | | addKitchenType(this.form).then(res => { |
| | | if (res.code == 200) { |
| | | this.$Message.success("添加成功"); |
| | | this.modelClose() |
| | | this.getDataList() |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }finally { |
| | | this.submitLoading = false |
| | | } |
| | | }); |
| | | }, |
| | | // 关闭弹窗 |
| | | modelClose() { |
| | | this.submitLoading = false |
| | | this.modelShow = false |
| | | }, |
| | | // 初始化数据 |
| | | init() { |
| | | this.getDataList(); |
| | | }, |
| | | // 分页 改变页码 |
| | | changePage(v) { |
| | | this.searchForm.pageNumber = v; |
| | | this.getDataList(); |
| | | }, |
| | | // 分页 改变页数 |
| | | changePageSize(v) { |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = v; |
| | | this.getDataList(); |
| | | }, |
| | | // 搜索 |
| | | handleSearch() { |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = 10; |
| | | this.getDataList(); |
| | | }, |
| | | // 起止时间从新赋值 |
| | | selectDateRange(v) { |
| | | if (v) { |
| | | this.searchForm.startDate = v[0]; |
| | | this.searchForm.endDate = v[1]; |
| | | } |
| | | }, |
| | | // 获取列表数据 |
| | | getDataList() { |
| | | this.loading = true; |
| | | getKitchenType(this.searchForm).then((res) => { |
| | | console.log(res) |
| | | this.loading = false; |
| | | if (res.code == 200) { |
| | | this.data = res.data; |
| | | this.total = res.total; |
| | | } |
| | | }); |
| | | this.total = this.data.length; |
| | | this.loading = false; |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.init(); |
| | | }, |
| | | }; |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .export { |
| | | margin: 10px 20px 10px 0; |
| | | } |
| | | .export-excel-wrapper { |
| | | display: inline; |
| | | } |
| | | .order-tab { |
| | | width: 950px; |
| | | height: 36px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | background-color: #f0f0f0; |
| | | padding: 0 10px; |
| | | margin-bottom: 10px; |
| | | div { |
| | | text-align: center; |
| | | padding: 4px 12px; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | } |
| | | .current { |
| | | background-color: #ffffff; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div> |
| | | <Card> |
| | | <Form |
| | | ref="searchForm" |
| | | @keydown.enter.native="handleSearch" |
| | | :model="searchForm" |
| | | inline |
| | | :label-width="70" |
| | | class="search-form" |
| | | > |
| | | <Form-item label="标题" prop="title"> |
| | | <Input |
| | | type="text" |
| | | v-model="searchForm.title" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | style="width: 160px" |
| | | /> |
| | | </Form-item> |
| | | <Form-item label="分类" prop="typeList"> |
| | | <Select |
| | | v-model="searchForm.typeList" |
| | | clearable |
| | | filterable |
| | | multiple |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | style="width: 160px" |
| | | > |
| | | <Option v-for="type in typeList" :key="type.id" :value="type.id">{{ type.typeName }}</Option> |
| | | </Select> |
| | | </Form-item> |
| | | <Form-item label="视频状态" prop="status"> |
| | | <Select |
| | | v-model="searchForm.status" |
| | | clearable |
| | | @on-clear="handleSearch" |
| | | @on-change="handleSearch" |
| | | style="width: 160px" |
| | | > |
| | | <Option value="99">待审核</Option> |
| | | <Option value="1">已发布</Option> |
| | | <Option value="0">已下架</Option> |
| | | <Option value="-1">审核未通过</Option> |
| | | </Select> |
| | | </Form-item> |
| | | <Button |
| | | @click="handleSearch" |
| | | type="primary" |
| | | icon="ios-search" |
| | | class="search-btn" |
| | | >搜索 |
| | | </Button |
| | | > |
| | | <Button |
| | | @click="handleVideoUpLoad" |
| | | type="primary" |
| | | icon="md-arrow-up" |
| | | class="search-btn" |
| | | >上传视频 |
| | | </Button |
| | | > |
| | | </Form> |
| | | <!-- 厨神视频上传--> |
| | | <Modal |
| | | v-model="upLoadVideoShow" |
| | | :title="uploadVideoForm.id?'编辑厨神视频':'上传厨神视频'" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | |
| | | <Form |
| | | :model="uploadVideoForm" |
| | | ref="uploadVideoForm" |
| | | :rules="uploadVideoFileRule" |
| | | > |
| | | <Row :gutter="24"> |
| | | <Col span="24"> |
| | | <Spin size="large" fix v-if="upLoadVideoLoading"> 文件上传中...</Spin> |
| | | </Col> |
| | | <Col span="12"> |
| | | <FormItem label="标题" prop="title"> |
| | | <Input placeholder="请输入标题" v-model="uploadVideoForm.title" |
| | | style="width: 200px" |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <!-- 刷新dom使用--> |
| | | <Col span="24"> |
| | | <FormItem label="刷新dom使用" prop="title" v-show="false"> |
| | | <Input placeholder="请输入标题" v-model="uploadVideoForm.temp" |
| | | style="width: 200px" |
| | | /> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="12" v-if="!uploadVideoForm.videoFileKey"> |
| | | <FormItem label="上传视频" prop="videoFileKey"> |
| | | <Upload |
| | | :multiple="true" |
| | | :before-upload="upLoadVideo" |
| | | accept="video/*" |
| | | action="" |
| | | > |
| | | <Button icon="ios-cloud-upload-outline">选择视频</Button> |
| | | </Upload> |
| | | </FormItem> |
| | | </Col> |
| | | |
| | | <Col span="24" v-else> |
| | | <FormItem label="视频"> |
| | | <video style="width: 150px;height: 150px" |
| | | controls |
| | | @loadedmetadata="getVideoDuration" |
| | | :poster="uploadVideoForm.showCoverUrl" |
| | | :autoplay="false" |
| | | id="remoteVideo" :src="uploadVideoForm.showVideoUrl" |
| | | ref="healthVideoInfo" |
| | | ></video> |
| | | </FormItem> |
| | | </Col> |
| | | |
| | | <Col span="12" v-show="uploadVideoForm.videoFileKey && !uploadVideoForm.coverUrl"> |
| | | <FormItem label="上传封面" prop="coverUrl"> |
| | | <Upload |
| | | :multiple="true" |
| | | :before-upload="upLoadImg" |
| | | accept="image/*" |
| | | action="" |
| | | > |
| | | <Button icon="ios-cloud-upload-outline">选择封面</Button> |
| | | </Upload> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24" style="padding-right:10px"> |
| | | <FormItem label="厨神标签" prop="checkKitchenType"> |
| | | <Select filterable multiple |
| | | style="width: 600px" |
| | | v-model="uploadVideoForm.checkKitchenType" |
| | | > |
| | | <Option v-for="item in kitchenType" :value="item.id" :key="item.id">{{ item.typeName }}</Option> |
| | | </Select> |
| | | </FormItem> |
| | | </Col> |
| | | <Col span="24"> |
| | | <div> |
| | | <Button type="primary" @click="clearCoverImage" v-show="uploadVideoForm.coverUrl">重新上传封面</Button> |
| | | <Button type="primary" @click="clearVideo" style="margin-left: 20px" |
| | | v-show="uploadVideoForm.videoFileKey">重新上传视频 |
| | | </Button> |
| | | </div> |
| | | </Col> |
| | | </Row> |
| | | |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="closeHealthVideo">关闭</Button> |
| | | <Button type="primary" @click="submitHealthVideo">确认</Button> |
| | | </div> |
| | | </Modal> |
| | | <Modal |
| | | v-model="playVideoShow" |
| | | :title="playVideoTitle" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <div class="video-warp"> |
| | | <video :src="playVideoUrl" autoplay controls style="width: 768px;height: 432px"/> |
| | | </div> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="playVideoClose">关闭</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | <Modal |
| | | v-model="auditingShow" |
| | | title="视频审核" |
| | | width="800" |
| | | :loading="auditingLoading" |
| | | :mask-closable="false" |
| | | > |
| | | |
| | | <Form |
| | | ref="auditingForm" |
| | | :model="auditingForm" |
| | | :label-width="70" |
| | | :rules="auditingRule" |
| | | > |
| | | <Form-item label="标题:"> |
| | | <div>{{ detail.title }}</div> |
| | | </Form-item> |
| | | <Form-item label="标签:"> |
| | | <div style="display: flex;flex-wrap: wrap"> |
| | | <div v-for="(tag, index) in detail.typeList" :key="'tag' + index" style="margin-right: 5px"> |
| | | <Tag color="red">{{ tag.tagName }}</Tag> |
| | | </div> |
| | | </div> |
| | | </Form-item> |
| | | <Form-item label="视频时长:" :label-width="72"> |
| | | <div>{{ formatSeconds(detail.videoDuration) }}</div> |
| | | </Form-item> |
| | | <Form-item class="video-warp" :label-width="0"> |
| | | <video :src="detail.videoUrl" autoplay controls style="width: 768px;height: 432px"/> |
| | | </Form-item> |
| | | <Form-item label="审核结果:" :label-width="100" prop="result"> |
| | | <RadioGroup v-model="auditingForm.result"> |
| | | <Radio :label="1">通过</Radio> |
| | | <Radio :label="0">不通过</Radio> |
| | | </RadioGroup> |
| | | </Form-item> |
| | | <Form-item v-show="auditingForm.result === 0" label="不通过原因:" :label-width="100" prop="reason"> |
| | | <Input |
| | | type="textarea" |
| | | v-model="auditingForm.reason" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </Form-item> |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="closeAuditing">关闭</Button> |
| | | <Button type="primary" @click="submitAuditing">确认</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | <Modal |
| | | v-model="videoDownShow" |
| | | title="视频下架" |
| | | width="800" |
| | | :mask-closable="false" |
| | | > |
| | | <Form :model="videoDownForm" :rules="videoDownRule" ref="videoDownForm"> |
| | | <FormItem label="下架原因:" :labelWidth="100" prop="reason"> |
| | | <editor ref="editor" @input="getReason"/> |
| | | </FormItem> |
| | | </Form> |
| | | <div slot="footer"> |
| | | <Button type="text" @click="closeVideoDown">关闭</Button> |
| | | <Button type="primary" @click="videoDown">确认</Button> |
| | | </div> |
| | | </Modal> |
| | | |
| | | <Table |
| | | :loading="loading" |
| | | border |
| | | :columns="columns" |
| | | :data="data" |
| | | ref="table" |
| | | sortable="custom" |
| | | @on-sort-change="changeSort" |
| | | @on-selection-change="showSelect" |
| | | > |
| | | <template slot-scope="{ row, index }" slot="typeList"> |
| | | <div v-for="(tag, index) in row.typeList" :key="'tag' + index" style="margin-top: 5px"> |
| | | <Tag color="red">{{ tag.typeName }}</Tag> |
| | | </div> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="videoFileKey"> |
| | | <div class="play-text" @click="playVideo(row.videoFileKey, row.title)">点击播放</div> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="videoDuration"> |
| | | <div>{{ formatSeconds(row.videoDuration) }}</div> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="recommend"> |
| | | <i-switch v-model="row.recommend" :before-change="() => handleBeforeChange(row)" true-color="#13ce66"/> |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="status"> |
| | | {{ transStatus(row.status) }} |
| | | </template> |
| | | <template slot-scope="{ row, index }" slot="action"> |
| | | <Button type="primary" size="small" style="margin-right: 5px" v-if="row.status === '99'" |
| | | @click="openAuditing(row)">审核 |
| | | </Button> |
| | | <Button type="error" size="small" style="margin-right: 5px" v-if="row.status === '1'" |
| | | @click="openVideoDown(row)">下架 |
| | | </Button> |
| | | <Button type="success" size="small" style="margin-right: 5px" v-else-if="row.status === '0'" |
| | | @click="videoUp(row)">上架 |
| | | </Button> |
| | | <Button type="success" size="small" style="margin-right: 5px" |
| | | @click="handleVideoUpLoad(row)">编辑 |
| | | </Button> |
| | | <Button type="success" size="small" style="margin-right: 5px" |
| | | @click="deleteHealthVideo(row)">删除 |
| | | </Button> |
| | | </template> |
| | | </Table> |
| | | |
| | | <Row type="flex" justify="end" class="mt_10"> |
| | | <Page |
| | | :current="searchForm.pageNumber" |
| | | :total="total" |
| | | :page-size="searchForm.pageSize" |
| | | @on-change="changePage" |
| | | @on-page-size-change="changePageSize" |
| | | :page-size-opts="[10, 20, 50]" |
| | | size="small" |
| | | show-total |
| | | show-elevator |
| | | show-sizer |
| | | ></Page> |
| | | </Row> |
| | | </Card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import {recommendSet, getVideoById, auditingVideo, up, down} from "@/api/video"; |
| | | import {addKitchenVideo, delKitchen, getKitchenVideos, updateKitchenVideo} from "@/api/kitchen-video"; |
| | | import {getFilePreview, getSts} from "@/api/file"; |
| | | import Editor from '@/components/editor/index.vue' |
| | | import COS from 'cos-js-sdk-v5'; |
| | | import {getFileKey} from "@/utils/file.js"; |
| | | import {getKitchenTypeAllList} from "@/api/kitchen"; |
| | | |
| | | export default { |
| | | name: "VideoList", |
| | | components: {Editor}, |
| | | data() { |
| | | return { |
| | | videoDownForm: { |
| | | id: '', |
| | | reason: '' |
| | | }, |
| | | videoDownRule: { |
| | | reason: [ |
| | | { |
| | | require: true, |
| | | message: '请输入下架原因', |
| | | trigger: 'blur', |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === '') { |
| | | callback(new Error('请输入下架原因')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | videoDownShow: false, // 视频下架 |
| | | videoDownMsg: '', // 下架提示信息 |
| | | auditingForm: { // 审核表单 |
| | | id: null, |
| | | result: null, |
| | | reason: '' |
| | | }, |
| | | auditingRule: { |
| | | result: [ |
| | | { |
| | | required: true, |
| | | message: '请选择视频审核结果', |
| | | trigger: 'change', |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined) { |
| | | callback(new Error('请选择视频审核结果')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | }, |
| | | uploadVideoFileRule: { |
| | | coverUrl: [ |
| | | { |
| | | required: true, |
| | | message: '请上传封面', |
| | | trigger: 'blur', |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === '') { |
| | | callback(new Error('请上传封面')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | videoFileKey: [ |
| | | { |
| | | required: true, |
| | | message: '请上传封面', |
| | | trigger: 'blur', |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === '') { |
| | | callback(new Error('请上传封面')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | checkKitchenType: [ |
| | | { |
| | | required: true, |
| | | message: '请选择厨神标签', |
| | | trigger: 'blur', |
| | | validator: (rule, value, callback) => { |
| | | console.log('验证值:-------------->', value, '类型:', typeof value); |
| | | if (value === null || value === undefined||value.length >5) { |
| | | callback(new Error('请选择厨神标签且不能超过5个')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | title: [ |
| | | { |
| | | required: true, |
| | | message: '请输入标题', |
| | | trigger: 'blur', |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined) { |
| | | callback(new Error('请输入标题')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | }, |
| | | detail: {}, // 视频详情信息 |
| | | auditingShow: false, // 审核弹窗 |
| | | upLoadVideoShow: false,//文件上传弹窗 |
| | | auditingLoading: false, // 审核弹窗 |
| | | upLoadVideoLoading: false,//上传视频 |
| | | playVideoShow: false, // 视频播放弹窗 |
| | | playVideoTitle: '', // 视频播放标题 |
| | | playVideoUrl: '', // 当前正在播放的视频地址 |
| | | modelShow: false, // 弹窗显隐 |
| | | modelTitle: '', // 弹窗title |
| | | loading: false, // 表单加载状态 |
| | | searchForm: { |
| | | // 搜索框初始化对象 |
| | | pageNumber: 1, // 当前页数 |
| | | pageSize: 10, // 页面大小 |
| | | title: '', // 标题 |
| | | typeList: [], // 标签 |
| | | status: '99' |
| | | }, |
| | | typeList: [], // 标签列表 |
| | | columns: [ |
| | | { |
| | | type: 'selection', |
| | | width: 60, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "标题", |
| | | key: "title", |
| | | minWidth: 240, |
| | | tooltip: true, |
| | | }, |
| | | { |
| | | title: "作者", |
| | | key: "authorName", |
| | | width: 130, |
| | | tooltip: true, |
| | | }, |
| | | { |
| | | title: "视频分类", |
| | | key: "typeList", |
| | | width: 180, |
| | | slot: "typeList", |
| | | }, |
| | | { |
| | | title: "视频内容", |
| | | key: "videoFileKey", |
| | | width: 170, |
| | | slot: "videoFileKey" |
| | | }, |
| | | { |
| | | title: "时长", |
| | | key: "videoDuration", |
| | | width: 80, |
| | | align: 'center', |
| | | slot: "videoDuration", |
| | | }, |
| | | { |
| | | title: "播放量", |
| | | key: "playNum", |
| | | width: 80, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "收藏数", |
| | | key: "collectNum", |
| | | width: 80, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "评论数", |
| | | key: "commentNum", |
| | | width: 80, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "首页推荐", |
| | | key: "recommend", |
| | | slot: "recommend", |
| | | width: 100, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "权重", |
| | | key: "weight", |
| | | width: 170, |
| | | }, |
| | | { |
| | | title: "状态", |
| | | key: "status", |
| | | slot: "status", |
| | | width: 120, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | title: "操作", |
| | | key: "action", |
| | | slot: "action", |
| | | align: "center", |
| | | width: 200, |
| | | }, |
| | | ], |
| | | data: [], // 表单数据 |
| | | kitchenType: [], // 厨神分类 |
| | | total: 0, // 表单数据总数 |
| | | selectCount: 0, // 已选数量 |
| | | selectList: [], // 已选数据列表 |
| | | uploadVideoForm: { |
| | | id: null, |
| | | checkKitchenType:[], |
| | | coverUrl: null, |
| | | videoFileKey: null, |
| | | videoFit: null, |
| | | videoDuration: null, |
| | | title: null, |
| | | videoContentType: null, |
| | | videoType: null, |
| | | showCoverUrl: null, |
| | | showVideoUrl: null, |
| | | temp: null |
| | | |
| | | }, |
| | | } |
| | | }, |
| | | created() { |
| | | this.getDataList(); |
| | | this.getTypes('') |
| | | }, |
| | | methods: { |
| | | // 秒转x分x秒 |
| | | formatSeconds(seconds) { |
| | | if (isNaN(seconds) || seconds < 0) return '0秒'; |
| | | |
| | | const mins = Math.floor(seconds / 60); |
| | | const secs = seconds % 60; |
| | | |
| | | if (mins === 0) return `${secs}秒`; |
| | | if (secs === 0) return `${mins}分`; |
| | | |
| | | return `${mins}分${secs}秒`; |
| | | }, |
| | | // 获取分类列表 |
| | | getTypes(typeName) { |
| | | let params = { |
| | | 'typeName': typeName |
| | | } |
| | | getKitchenTypeAllList(params).then(res => { |
| | | this.typeList = res.data |
| | | }) |
| | | }, |
| | | // 获取富文本编辑器的内容 |
| | | getReason(content) { |
| | | this.videoDownForm.reason = content |
| | | }, |
| | | //重新上传封面 |
| | | clearCoverImage() { |
| | | this.$set(this.uploadVideoForm, 'coverUrl', ''); |
| | | this.$set(this.uploadVideoForm, 'showCoverUrl', ''); |
| | | this.$set(this.uploadVideoForm, 'temp', new Date().getTime()); |
| | | }, |
| | | //重新上传视频 |
| | | clearVideo() { |
| | | this.clearCoverImage(); |
| | | this.$set(this.uploadVideoForm, 'videoFileKey', ''); |
| | | this.$set(this.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({ |
| | | title: "操作确认", |
| | | content: "您确认要上架视频【 " + row.title + "】吗?", |
| | | loading: true, |
| | | onOk: () => { |
| | | up(row.id).then(res => { |
| | | this.$Modal.remove(); |
| | | if (res.code == 200) { |
| | | this.$Message.success("视频上架成功"); |
| | | this.getDataList(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // 视频下架 |
| | | videoDown() { |
| | | this.$refs.videoDownForm.validate((valid) => { |
| | | if (valid) { |
| | | down(this.videoDownForm).then(res => { |
| | | this.$Message.success("下架成功") |
| | | this.closeVideoDown() |
| | | this.getDataList() |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | // 关闭视频下架 |
| | | closeVideoDown() { |
| | | this.videoDownShow = false |
| | | this.videoDownForm = { |
| | | id: '', |
| | | reason: '' |
| | | } |
| | | this.$refs.editor.setContent('') |
| | | }, |
| | | // 视频下架 |
| | | openVideoDown(row) { |
| | | this.videoDownForm.id = row.id |
| | | this.videoDownShow = true |
| | | }, |
| | | // 视频发布/修改 |
| | | //todo 1 |
| | | submitHealthVideo() { |
| | | console.log(this.uploadVideoForm) |
| | | try { |
| | | this.upLoadVideoLoading = true |
| | | this.$refs.uploadVideoForm.validate((valid) => { |
| | | if (valid) { |
| | | // 修改 |
| | | if (this.uploadVideoForm.id) { |
| | | console.log(this.uploadVideoForm) |
| | | updateKitchenVideo(this.uploadVideoForm).then(res => { |
| | | this.$Message.success("修改完成") |
| | | this.closeHealthVideo() |
| | | this.getDataList() |
| | | }) |
| | | } else { |
| | | addKitchenVideo(this.uploadVideoForm).then(res => { |
| | | this.$Message.success("添加完成") |
| | | this.closeHealthVideo() |
| | | this.getDataList() |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } finally { |
| | | this.upLoadVideoLoading = false |
| | | } |
| | | }, |
| | | //获取标签 |
| | | getKitchenTypeList(e){ |
| | | const typeParam = {typeName:e} |
| | | getKitchenTypeAllList(typeParam).then(res => { |
| | | this.kitchenType = res.data |
| | | }) |
| | | |
| | | }, |
| | | |
| | | // 关闭窗口 |
| | | closeHealthVideo() { |
| | | // |
| | | this.uploadVideoForm = {}; |
| | | this.upLoadVideoShow = false; |
| | | }, |
| | | // 提交审核结果 |
| | | submitAuditing() { |
| | | console.log(this.auditingForm, "sb") |
| | | this.$refs.auditingForm.validate((valid) => { |
| | | if (valid) { |
| | | auditingVideo(this.auditingForm).then(res => { |
| | | this.$Message.success("审核完成") |
| | | this.closeAuditing() |
| | | this.getDataList() |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | // 审核结果变化 |
| | | resultChange(selected) { |
| | | this.auditingForm.result = selected === '通过' ? 1 : 0 |
| | | console.log(this.auditingForm.result) |
| | | }, |
| | | closeAuditing() { |
| | | this.auditingForm = { |
| | | id: null, |
| | | result: null, |
| | | reason: '' |
| | | } |
| | | this.detail = {} |
| | | this.auditingShow = false |
| | | }, |
| | | // 打开审核弹窗 |
| | | openAuditing(row) { |
| | | this.auditingShow = true |
| | | this.auditingLoading = true |
| | | this.auditingForm.id = row.id |
| | | getVideoById(row.id).then(res => { |
| | | this.detail = res.data |
| | | this.auditingLoading = false |
| | | }) |
| | | }, |
| | | // 打开编辑弹窗 |
| | | deleteHealthVideo(row) { |
| | | console.log('删除测试', row) |
| | | this.$Modal.confirm({ |
| | | title: "操作确认", |
| | | content: "您确认要删除视频【 " + row.title + "】吗?", |
| | | loading: true, |
| | | onOk: () => { |
| | | delKitchen(row.id).then(res => { |
| | | this.$Modal.remove(); |
| | | if (res.code === 200) { |
| | | this.$Message.success("视频删除成功"); |
| | | this.getDataList(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | // 翻译状态 |
| | | transStatus(status) { |
| | | switch (status) { |
| | | case '99': |
| | | return '待审核' |
| | | case '1': |
| | | return '已发布' |
| | | case '0': |
| | | return '已下架' |
| | | case '-1': |
| | | return '审核未通过' |
| | | default: |
| | | return '未知' |
| | | } |
| | | }, |
| | | // 开启或关闭推荐的方法 |
| | | handleBeforeChange(row) { |
| | | let content = "" |
| | | if (row.recommend) { |
| | | content = '确认要关闭首页推荐吗?' |
| | | } else { |
| | | content = '确认要开启首页推荐吗?' |
| | | } |
| | | return new Promise((resolve) => { |
| | | this.$Modal.confirm({ |
| | | title: '操作提醒', |
| | | content: content, |
| | | onOk: () => { |
| | | recommendSet({id: row.id, recommend: !row.recommend}).then(res => { |
| | | this.$Message.success(res.msg); |
| | | resolve(); |
| | | }) |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | // 关闭视频播放 |
| | | playVideoClose() { |
| | | this.playVideoTitle = ''; |
| | | this.playVideoUrl = ''; |
| | | this.playVideoShow = false |
| | | }, |
| | | // 点击播放视频 |
| | | playVideo(fileKey, title) { |
| | | this.playVideoTitle = title; |
| | | |
| | | getFilePreview(fileKey).then(res => { |
| | | this.playVideoUrl = res.data |
| | | this.playVideoShow = true |
| | | }) |
| | | }, |
| | | // 搜索 |
| | | handleSearch() { |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = 10; |
| | | this.getDataList(); |
| | | }, |
| | | // 获取列表数据 |
| | | getDataList() { |
| | | this.loading = true; |
| | | getKitchenVideos(this.searchForm).then((res) => { |
| | | console.log(res) |
| | | this.loading = false; |
| | | if (res.code === 200) { |
| | | this.data = res.data; |
| | | this.total = res.total; |
| | | } |
| | | }); |
| | | this.total = this.data.length; |
| | | this.loading = false; |
| | | }, |
| | | showSelect(e) { |
| | | this.selectList = e.map(d => d.id); |
| | | this.selectCount = e.length; |
| | | }, |
| | | // 排序 |
| | | changeSort(e) { |
| | | this.searchForm.sort = e.key; |
| | | this.searchForm.order = e.order; |
| | | if (e.order == "normal") { |
| | | this.searchForm.order = ""; |
| | | } |
| | | this.getDataList(); |
| | | }, |
| | | // 分页 改变页码 |
| | | changePage(v) { |
| | | this.searchForm.pageNumber = v; |
| | | this.getDataList(); |
| | | }, |
| | | |
| | | // 分页 改变页数 |
| | | changePageSize(v) { |
| | | this.searchForm.pageNumber = 1; |
| | | this.searchForm.pageSize = v; |
| | | this.getDataList(); |
| | | }, |
| | | |
| | | handleVideoUpLoad(row) { |
| | | this.uploadVideoForm = {}; |
| | | this.upLoadVideoShow = true; |
| | | console.log(row) |
| | | if (row.id) { |
| | | this.uploadVideoForm.id = row.id; |
| | | this.uploadVideoForm.showVideoUrl = row.videoUrl |
| | | this.uploadVideoForm.videoFileKey = row.videoFileKey; |
| | | this.uploadVideoForm.coverUrl = row.coverUrl; |
| | | this.uploadVideoForm.showCoverUrl = row.coverShowUrl; |
| | | this.uploadVideoForm.title = row.title; |
| | | this.uploadVideoForm.checkKitchenType = row.typeList.map(item => {return item.id}); |
| | | } |
| | | this.getKitchenTypeList(); |
| | | }, |
| | | async upLoadVideo(file) { |
| | | try { |
| | | this.$nextTick(() => { |
| | | 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(this.uploadVideoForm) |
| | | this.$nextTick(() => { |
| | | this.uploadVideoForm.videoFileKey = fileKey; |
| | | this.uploadVideoForm.showVideoUrl = sts.data.endpoint + "/" + fileKey; |
| | | }) |
| | | console.log("上传成功", upData) |
| | | const duration = this.$refs.healthVideoInfo.duration; |
| | | console.log('-测试获取时间信息---------------->', duration); |
| | | } catch (e) { |
| | | console.log("上传失败", upData) |
| | | } finally { |
| | | this.$nextTick(() => { |
| | | this.upLoadVideoLoading = false; |
| | | }) |
| | | } |
| | | return false; |
| | | }, |
| | | async upLoadImg(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.uploadVideoForm.coverUrl = fileKey; |
| | | this.uploadVideoForm.showCoverUrl = sts.data.endpoint + "/" + fileKey; |
| | | }) |
| | | |
| | | } catch (e) { |
| | | console.log("上传失败", upData) |
| | | } finally { |
| | | this.upLoadVideoLoading = false; |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .play-text { |
| | | width: 100%; |
| | | text-align: center; |
| | | color: #2d8cf0; |
| | | } |
| | | |
| | | .play-text:hover { |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .video-warp { |
| | | width: 786px; |
| | | height: 432px; |
| | | } |
| | | |
| | | .data-item { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .showCoverImg { |
| | | position: relative; |
| | | } |
| | | |
| | | .coverImgRemove { |
| | | position: absolute; |
| | | top: 15px; |
| | | right: -15px; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div> |
| | | <Row v-for="goods in goodsList" :key="goods.goodsId"> |
| | | <Row style="width:100%;align-items: center"> |
| | | <Col span="6"> |
| | | <img :src="goods.thumbnail" style="width: 150px;height: 150px"/> |
| | | </Col> |
| | | <Col span="6"> |
| | | <p>商品名称: {{ goods.goodsName }}</p> |
| | | </Col> |
| | | <Col span="6"> |
| | | <p>商品单价: ¥{{ goods.price }}</p> |
| | | </Col> |
| | | <Col span="6"> |
| | | <p>商品数量: {{ goods.goodsNum }}</p> |
| | | </Col> |
| | | </Row> |
| | | </Row> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "GoodsExpandRow", |
| | | props: { |
| | | goodsList: { |
| | | type: Array |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | |
| | | <Modal |
| | | v-model="auditingShow" |
| | | title="视频审核" |
| | | width="800" |
| | | width="1200" |
| | | :loading="auditingLoading" |
| | | :mask-closable="false" |
| | | > |
| | |
| | | </div> |
| | | </div> |
| | | </Form-item> |
| | | <Form-item label="视频时长:" :label-width="72"> |
| | | <Form-item v-if="detail.videoContentType === 'video'" label="视频时长:" :label-width="72"> |
| | | <div>{{formatSeconds(detail.videoDuration)}}</div> |
| | | </Form-item> |
| | | <Form-item class="video-warp" :label-width="0"> |
| | | <video :src="detail.videoUrl" autoplay controls style="width: 768px;height: 432px"/> |
| | | <Form-item v-if="detail.videoContentType === 'img'" label="图片张数:" :label-width="72"> |
| | | <div>{{detail.imgs.length}}</div> |
| | | </Form-item> |
| | | <Form-item v-if="detail.videoContentType === 'video'" class="video-warp" :label-width="0"> |
| | | <Row> |
| | | <Col span="11"> |
| | | <video :src="detail.videoUrl" autoplay controls style="width: 500px;height: 300px"/> |
| | | </Col> |
| | | <Col span="13" style="max-height: 300px;overflow-y: scroll"> |
| | | <Row v-for="goods in detail.goodsList" :key="goods.goodsId" style="width: 100%"> |
| | | <Row style="width:100%;align-items: center"> |
| | | <Col span="6"> |
| | | <img :src="goods.thumbnail" style="width: 100px;height: 100px"/> |
| | | </Col> |
| | | <Col span="10"> |
| | | <p>商品名称: {{ goods.goodsName }}</p> |
| | | </Col> |
| | | <Col span="4"> |
| | | <p>商品单价: ¥{{ goods.price }}</p> |
| | | </Col> |
| | | <Col span="4"> |
| | | <p>商品数量: {{ goods.goodsNum }}</p> |
| | | </Col> |
| | | </Row> |
| | | </Row> |
| | | </Col> |
| | | </Row> |
| | | |
| | | </Form-item> |
| | | <Form-item v-if="detail.videoContentType === 'img'" :label-width="0"> |
| | | <div style="display: flex;flex-direction: row;flex-wrap: wrap"> |
| | | <div v-for="img in detail.imgs" :key="img" class="img-warp"> |
| | | <img :src="img" class="image"> |
| | | </div> |
| | | </div> |
| | | |
| | | </Form-item> |
| | | <Form-item label="审核结果:" :label-width="100" prop="result"> |
| | | <RadioGroup v-model="auditingForm.result"> |
| | |
| | | import {getVideoTagList} from "@/api/videoTag"; |
| | | import {getFilePreview} from "@/api/file"; |
| | | import Editor from '@/components/editor/index.vue' |
| | | import GoodsExpandRow from '@/views/video/GoodsExpandRow' |
| | | export default { |
| | | name: "VideoList", |
| | | components: {Editor}, |
| | | components: {Editor,GoodsExpandRow}, |
| | | data() { |
| | | return { |
| | | videoDownForm: { |
| | |
| | | type: 'selection', |
| | | width: 60, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | width: 60, |
| | | type: 'expand', |
| | | render: (h, params) => { |
| | | return h(GoodsExpandRow, { |
| | | props: { |
| | | goodsList: params.row.goodsList |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | { |
| | | title: "标题", |
| | |
| | | cursor: pointer; |
| | | } |
| | | .video-warp { |
| | | width: 786px; |
| | | height: 432px; |
| | | width: 100%; |
| | | height: 350px; |
| | | } |
| | | .data-item { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .img-warp { |
| | | padding: 10px; |
| | | } |
| | | .image { |
| | | width: 150px; |
| | | height: 200px; |
| | | } |
| | | </style> |
| | |
| | | "@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" v-if=" baseInfoForm.goodsVideo ==null || baseInfoForm.goodsVideo ===''"> |
| | | <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" v-if="!(baseInfoForm.goodsGalleryFiles !=null &&baseInfoForm.goodsGalleryFiles.length>0)"> |
| | | <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" |
| | |
| | | <!--<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; |
| | |
| | | }, |
| | | // 移除已选图片 |
| | | 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) && !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> |