master
lion 7 months ago
parent 29d4a3d45c
commit ec3f9edf04

@ -55,6 +55,15 @@ export function destroy(params) {
})
}
export function imports(params) {
return request({
method: "get",
url: "/api/admin/product/import",
params
})
}

@ -48,7 +48,7 @@ export async function download(url, method = "get", info, filename) {
url,
method,
responseType: "blob",
timeout: 10000,
timeout: 30000,
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=utf-8",

@ -17,9 +17,6 @@
style="margin-top: 10px"
drag
:action="action"
:data="{
table_name: tableName,
}"
:headers="{
Authorization: `Bearer ${getToken()}`,
}"
@ -44,6 +41,8 @@ import * as XLSX from "xlsx";
import { saveAs } from "file-saver";
import { getToken } from "@/utils/auth";
import { imports } from "@/api/system/baseForm";
import { imports as importProduct } from "@/api/product/index";
export default {
props: {
formInfo: {
@ -54,10 +53,9 @@ export default {
},
data() {
return {
action: `${process.env.VUE_APP_BASE_API}/api/admin/base-form/excel-show`,
action: `${process.env.VUE_APP_BASE_API}/api/admin/product/import`,
dialogVisible: false,
headers: [],
tableList: [],
table: [],
};
@ -104,8 +102,7 @@ export default {
},
imports() {
imports({
table_name: this.tableName,
importProduct({
data: this.tableList
}).then(res => {
console.log(res)

@ -59,6 +59,18 @@
</div>
</div>
</template>
<template v-slot:shipping_region>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>States/Province
</div>
<div class="xy-table-item-content">
<el-input placeholder="Please Input" style="width:100%" v-model="form.shipping_region"></el-input>
</div>
</div>
</template>
<template v-slot:organization>
<div class="xy-table-item">
<div class="xy-table-item-label" multiple collapse-tags style="font-weight: bold">
@ -128,6 +140,7 @@
full_name: '',
email: '',
region: '',
shipping_region:'',
organization: '',
question: '',
additional: '',
@ -157,6 +170,13 @@
page: 1
})
this.productList = res.data
this.productList.unshift({
id:0,
name:'None'
},{
id:-1,
name:'Other'
})
},
submit() {
if (this.id) {
@ -201,6 +221,7 @@
full_name: '',
email: '',
region: '',
shipping_region:'',
organization: '',
question: '',
additional: '',

@ -42,7 +42,10 @@
<template slot-scope="scope">
<template v-if="scope.row.order_products && scope.row.order_products.length>0">
<template v-for="item in scope.row.order_products">
<div class="product-item">{{item.product.name}}</div>
<el-tooltip class="item" effect="dark" :content="item.product.name" placement="top">
<div class="product-item">{{item.product.name}}</div>
</el-tooltip>
</template>
</template>
</template>
@ -150,6 +153,11 @@
label: 'Address',
align: 'left',
width: 360
}, {
prop: 'card',
label: 'Card',
align: 'left',
width: 240
}, {
prop: 'created_at',
label: 'Created At',

@ -85,12 +85,63 @@
<div class="xy-table-item-content">
<el-upload :action="action" class='upload-demo' :limit="1" list-type="picture-card"
accept=".PNG,.jpg,.jpeg,.bmp,.svg" :file-list="pictureList" ref="pictureUpload" :auto-upload="true"
:on-success="handlesuccessP" :on-remove="handleRemoveP">
:on-success="(response, file, fileList)=>{return handlesuccessP(response, file, fileList,'picture_id')}"
:on-remove="(file, fileList)=>{return handleRemoveP(file, fileList,'picture_id')}">
<i class="el-icon-plus"></i>
</el-upload>
</div>
</div>
</template>
</template>
<template v-slot:picture_id_2>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>Second Poster
</div>
<div class="xy-table-item-content">
<el-upload :action="action" class='upload-demo' :limit="1" list-type="picture-card"
accept=".PNG,.jpg,.jpeg,.bmp,.svg" :file-list="pictureList2" ref="pictureUpload" :auto-upload="true"
:on-success="(response, file, fileList)=>{return handlesuccessP(response, file, fileList,'picture_id_2')}"
:on-remove="(file, fileList)=>{return handleRemoveP(file, fileList,'picture_id_2')}">
<i class="el-icon-plus"></i>
</el-upload>
</div>
</div>
</template>
<template v-slot:video_image_id>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>Video Poster
</div>
<div class="xy-table-item-content">
<el-upload :action="action" class='upload-demo' :limit="1" list-type="picture-card"
accept=".PNG,.jpg,.jpeg,.bmp,.svg" :file-list="videoPosterList" ref="pictureUpload" :auto-upload="true"
:on-success="(response, file, fileList)=>{return handlesuccessP(response, file, fileList,'video_image_id')}"
:on-remove="(file, fileList)=>{return handleRemoveP(file, fileList,'video_image_id')}">
<i class="el-icon-plus"></i>
</el-upload>
</div>
</div>
</template>
<template v-slot:video_id>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>Video
</div>
<div class="xy-table-item-content">
<el-upload :action="action" :limit='1' class='upload-demo' :file-list="videoList"
accept=".mp4,.ogg,.flv,.avi,.wmv,.rmvb,.mov"
ref="pictureUpload" :auto-upload="true" :on-progress="handleProgress"
:on-success="(response, file, fileList)=>{return handlesuccessP(response, file, fileList,'video_id')}"
:on-remove="(file, fileList)=>{return handleRemoveP(file, fileList,'video_id')}">
<el-button size="small" type="primary">upload</el-button>
</el-upload>
<el-progress v-if="showProgress" :percentage="uploadProgress"></el-progress>
</div>
</div>
</template>
<template v-slot:description>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
@ -308,10 +359,15 @@
uploadOther: {
token: ""
},
action: `${process.env.VUE_APP_UPLOAD_API}`,
action: `${process.env.VUE_APP_UPLOAD_API}`,
showProgress:false,
uploadProgress:0,
pcSubList: [], // category id
categoryList: [],
pictureList: [],
pictureList: [],
pictureList2: [],
videoPosterList:[],
videoList:[],
downloadsList: [],
applicationsList: [],
selectList: [],
@ -354,7 +410,10 @@
sort: 0,
is_recommend: 0,
is_sample: 0,
picture_id: '',
picture_id: '',
picture_id_2:'',
video_image_id:'',
video_id:'',
description: '',
product_category_phase: [],
@ -400,17 +459,47 @@
return
}
this.downloadsList = fileList
},
handleProgress(event, file, fileList) {
this.showProgress = true;
this.uploadProgress = event.percent;
},
handleRemoveP(file, fileList) {
this.pictureList = fileList
handleRemoveP(file, fileList,type) {
if(type=='picture_id'){
this.pictureList = fileList
}else if(type=='picture_id_2'){
this.pictureList2 = fileList
}else if(type=='video_image_id'){
this.videoPosterList = fileList
}else if(type=='video_id'){
this.videoList = fileList
}
},
handlesuccessP(response, file, fileList) {
handlesuccessP(response, file, fileList,type) {
if (response && response.hasOwnProperty('errcode')) {
this.$Message.warning(response.errmsg || '')
this.pictureList = []
this.$Message.warning(response.errmsg || '')
if(type=='picture_id'){
this.pictureList = []
}else if(type=='picture_id_2'){
this.pictureList2 = []
}else if(type=='video_image_id'){
this.videoPosterList = []
}else if(type=='video_id'){
this.videoList = []
}
return
}
this.pictureList = fileList
}
if(type=='picture_id'){
this.pictureList = fileList
}else if(type=='picture_id_2'){
this.pictureList2 = fileList
}else if(type=='video_image_id'){
this.videoPosterList = fileList
}else if(type=='video_id'){
this.videoList = fileList
}
},
async getCategoryList() {
@ -612,7 +701,49 @@
this.form.picture_id = p_files[0]
} else {
this.form.picture_id = ''
}
}
let p2_files = []
if (this.pictureList2.length > 0) {
for (var h of this.pictureList2) {
if (h.response) {
p2_files.push(h.response.id)
} else {
p2_files.push(h.id)
}
}
this.form.picture_id_2 = p_files[0]
} else {
this.form.picture_id_2 = ''
}
let v_files = []
if (this.videoPosterList.length > 0) {
for (var h of this.videoPosterList) {
if (h.response) {
v_files.push(h.response.id)
} else {
v_files.push(h.id)
}
}
this.form.video_image_id = v_files[0]
} else {
this.form.video_image_id = ''
}
let v2_files = []
if (this.videoList.length > 0) {
for (var h of this.videoList) {
if (h.response) {
v2_files.push(h.response.id)
} else {
v2_files.push(h.id)
}
}
this.form.video_id = v2_files[0]
} else {
this.form.video_id = ''
}
// application
let a_ids = []
if (this.applicationsList.length > 0) {
@ -710,6 +841,27 @@
id: res.picture.id,
url: res.picture.url
})
}
if (res.picture_id2) {
this.pictureList2.push({
name: res.picture_id2.original_name,
id: res.picture_id2.id,
url: res.picture_id2.url
})
}
if (res.video_image) {
this.videoPosterList.push({
name: res.video_image.original_name,
id: res.video_image.id,
url: res.video_image.url
})
}
if (res.video) {
this.videoList.push({
name: res.video.original_name,
id: res.video.id,
url: res.video.url
})
}
})
@ -747,10 +899,15 @@
this.showWang = false
this.showPacking = false
this.downloadsList = []
this.pictureList = []
this.pictureList = []
this.pictureList2 = []
this.videoPosterList = []
this.videoList = []
this.applicationsList = []
this.selectList = []
this.pcSubList = []
this.pcSubList = []
this.showProgress = false
this.uploadProgress = 0
this.form = {
product_category_links_by_sub: [],
name: '',
@ -758,7 +915,10 @@
sort: 0,
is_recommend: 0,
is_sample: 0,
picture_id: '',
picture_id: '',
picture_id_2:'',
video_image_id:'',
video_id:'',
description: '',
product_category_phase: [],
product_category_details: [],
@ -790,7 +950,11 @@
{
flex-basis: 100%;
}
::v-deep .picture_id,
::v-deep .picture_id_2,
::v-deep .video_image_id{
flex-basis: 50%;
}
::v-deep .sort,
::v-deep .time,
::v-deep .is_recommend,

@ -86,7 +86,7 @@
<template v-slot:is_visible>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>Visible
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>Product Visible
</div>
<div class="xy-table-item-content">
<el-radio-group v-model="form.is_visible">
@ -112,7 +112,7 @@
<template v-slot:show_price>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>Web Visibility
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>Price Visible
</div>
<div class="xy-table-item-content">
<el-radio-group v-model="form.show_price" @change="changeWeb">

@ -0,0 +1,154 @@
<template>
<div>
<el-dialog :visible.sync="dialogVisible" title="import" width="740px">
<!-- <div class="title">模板下载</div> -->
<!-- <el-button
style="margin-top: 10px"
size="small"
type="primary"
@click="exportExcel(new Date().getTime().toString())"
>模板下载</el-button
> -->
<div style="color: red; margin-top: 10px">
Do not modify the title name of the template when importing
</div>
<el-upload
style="margin-top: 10px"
drag
:action="action"
:headers="{
Authorization: `Bearer ${getToken()}`,
}"
:on-success="uploadSuccess"
:on-error="uploadFail"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">Drag the file here, or <em>click Upload</em></div>
<div class="el-upload__tip" slot="tip">Only xls/xlsx files can be uploaded</div>
</el-upload>
<!-- <div class="title" style="margin-top: 10px;">数据预览</div>
<Table :data="tableList" :columns="table" style="margin-top: 10px;"></Table>
<div style="font-size: 12px;zoom: 0.8;">总共数据{{ tableList.length }}</div> -->
<!-- <el-button type="primary" size="small" style="margin-top: 10px;" @click="imports"></el-button> -->
</el-dialog>
</div>
</template>
<script>
import * as XLSX from "xlsx";
import { saveAs } from "file-saver";
import { getToken } from "@/utils/auth";
import { imports } from "@/api/system/baseForm";
import { imports as importProduct } from "@/api/product/index";
export default {
props: {
formInfo: {
type: Array,
default: () => [],
},
tableName: String,
},
data() {
return {
action: `${process.env.VUE_APP_BASE_API}/api/admin/product/import`,
dialogVisible: false,
headers: [],
tableList: [],
table: [],
};
},
methods: {
getToken,
show() {
this.dialogVisible = true;
},
hidden() {
this.dialogVisible = false;
},
//
uploadFail(err) {
console.log(err);
this.$message({
message: "Upload failed.",
type: "error",
});
},
uploadSuccess(response) {
this.tableList = response;
this.$message({
message: `Upload successful`,
type: "success",
});
this.hidden();
this.$emit('refresh')
},
exportExcel(sheetName) {
const data = [this.headers.map((header) => header.title)];
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.aoa_to_sheet(data);
XLSX.utils.book_append_sheet(wb, ws, sheetName);
const wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array",
});
saveAs(
new Blob([wbout], { type: "application/octet-stream" }),
`${sheetName}.xlsx`
);
},
imports() {
importProduct({
data: this.tableList
}).then(res => {
console.log(res)
this.$message({
type: 'success',
message: `成功导入${res.total}`
})
})
this.hidden();
this.$emit('refresh')
}
},
computed: {},
watch: {
formInfo(newVal) {
if (newVal && newVal instanceof Array) {
this.table = this.headers = newVal.map((i) => {
return {
key: i.field,
title: i.name,
};
});
}
},
},
};
</script>
<style scoped lang="scss">
.title {
font-size: 15px;
font-weight: 600;
padding: 8px 4px;
position: relative;
&::before {
content: '';
width: 4px;
background: $primaryColor;
position: absolute;
top: 8px;
bottom: 8px;
left: -8px;
}
}
</style>

@ -53,6 +53,9 @@
</div>
<div>
<el-button type="primary" size="small" @click="exportExcel">export</el-button>
</div>
<div>
<el-button type="primary" size="small" @click="importTable">import</el-button>
</div>
</div>
</div>
@ -85,7 +88,8 @@
</el-table-column>
</template>
</xy-table>
<addProduct ref="addProduct" @refresh="getList"></addProduct>
<addProduct ref="addProduct" @refresh="getList"></addProduct>
<imports ref="imports" @refresh="getList"></imports>
</div>
</template>
@ -103,10 +107,12 @@
} from "@/utils/downloadRequest";
import {
getToken
} from '@/utils/auth'
} from '@/utils/auth'
import imports from "./components/imports.vue"
export default {
components: {
addProduct
addProduct,
imports
},
data() {
return {
@ -182,7 +188,7 @@
},
{
prop: 'is_visible',
label: 'Visible',
label: 'Product Visible',
align: 'center',
width: 120,
is_text:true,
@ -204,7 +210,7 @@
},
{
prop: 'show_price',
label: 'Web Visibility',
label: 'Price Visible',
align: 'center',
width: 180,
is_text:true,
@ -231,7 +237,10 @@
this.getCategoryList()
this.getList()
},
methods: {
methods: {
importTable(row) {
this.$refs.imports.show()
},
editProduct(type, id) {
if (type == 'editor') {
this.$refs.addProduct.id = id

Loading…
Cancel
Save