This commit is contained in:
pikachu1995@126.com
2024-01-22 15:24:41 +08:00
385 changed files with 241037 additions and 565 deletions

View File

@@ -231,6 +231,13 @@ export const updateGoodsSkuStocks = params => {
"Content-Type": "application/json"
});
};
// 更新商品库存预警
export const updateGoodsAlertStocks = params => {
return putRequest("/goods/goods/update/alert/stocks", params, {
"Content-Type": "application/json"
});
};
// 获取商品分页列表
export const getGoodsListDataSeller = params => {
return getRequest("/goods/goods/list", params);

View File

@@ -387,3 +387,24 @@ export const editOtherUser = (id, params) => {
// export const searchDepartment = (params) => {
// return getRequest("/permission/department/search", params);
// };
// 获取文件目录列表
export const getFileDirectory = () => {
return getRequest(commonUrl+`/common/resource/fileDirectory`);
};
// 添加文件目录
export const addFileDirectory = (params) => {
return postRequestWithNoForm(commonUrl+`/common/resource/fileDirectory`,params);
};
// 修改文件目录
export const updateFileDirectory = (params) => {
return putRequestWithNoForm(commonUrl+`/common/resource/fileDirectory`,params);
};
// 删除文件目录
export const delFileDirectory = (id) => {
return deleteRequest(commonUrl+`/common/resource/fileDirectory/${id}`);
};

View File

@@ -141,3 +141,20 @@ export const getReceiptPage = params => {
export const invoicing = id => {
return postRequest(`/trade/receipt/${id}/invoicing`);
};
//查询包裹列表
export const getPackage = (orderSn) => {
return getRequest(`/order/order/getPackage/${orderSn}`);
}
//分包裹发货
export const partDelivery = (orderSn,params) => {
return postRequest(`/order/order/${orderSn}/partDelivery`,params,{
"Content-type": "application/json"
})
}
//查询物流
export const getTracesList = (sn) => {
return getRequest(`/order/order/getTracesList/${sn}`);
}

View File

@@ -140,8 +140,10 @@ export default {
this.loading = true;
let that = this;
setTimeout(function () {
that.init();
that.$Message.success("刷新成功");
that.loading = false;
}, 1000);
}, 500);
},
//添加子分类
addChildren(v) {
@@ -261,4 +263,7 @@ export default {
min-height: 100vh;
height: auto;
}
.operation {
margin-bottom: 10px;
}
</style>

View File

@@ -342,18 +342,14 @@ div.base-info-item {
}
.sku-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, 0.2);
margin-right: 4px;
margin-right: 8px;
}
.preview-picture {

View File

@@ -0,0 +1,420 @@
<template>
<div class="search">
<Card>
<Row @keydown.enter.native="handleSearch">
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form"
>
<Form-item label="商品名称" prop="goodsName">
<Input
type="text"
v-model="searchForm.goodsName"
placeholder="请输入商品名称"
clearable
style="width: 200px"
/>
</Form-item>
<Form-item label="商品分类" prop="category">
<Cascader
v-model="category"
placeholder="请选择商品分类"
style="width: 200px"
:data="categoryList"
></Cascader>
</Form-item>
<Button @click="handleSearch" type="primary" class="search-btn">搜索</Button>
<Button @click="handleReset" class="search-btn">重置</Button>
</Form>
</Row>
<Tabs @on-click="switchTabs" value="updateStock" v-model="stockType">
<TabPane label="预警商品" name="warnList">
<Table
class="mt_10"
border
:loading="loading"
:columns="columns"
:data="warnData"
ref="table"
>
</Table>
</TabPane>
<TabPane label="设置预警" name="warnSetting">
<Table
class="mt_10"
border
:loading="loading"
:columns="settingColumns"
:data="skuAllData"
ref="table"
>
<template slot="alertQuantitySlot" slot-scope="{ row }">
<Input type="number" v-model="row.alertQuantity" clearable placeholder="请输入预警库存" @on-blur="updateWarnStock(row)" @on-change="checkVal(row)" />
</template>
</Table>
</TabPane>
</Tabs>
<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>
<Modal
title="更新库存"
v-model="updateStockModalVisible"
:mask-closable="false"
:width="610"
>
<Table
class="mt_10"
:columns="updateStockColumns"
:data="stockList"
border
></Table>
<div slot="footer">
<Button type="text" @click="updateStockModalVisible = false">取消</Button>
<Button type="primary" @click="updateStock">更新</Button>
</div>
</Modal>
</div>
</template>
<script>
import {
getGoodsSkuListDataSeller,
getGoodsListDataByStockSeller,
updateGoodsAlertStocks,
updateGoodsSkuStocks,
getGoodsCategoryAll
} from "@/api/goods";
import * as API_Shop from "@/api/shops";
export default {
name: "goods",
data() {
return {
id: "", //要操作的id
loading: true, // 表单加载状态
updateStockModalVisible: false, // 更新库存模态框显隐
stockAllUpdate: undefined, // 更新库存数量
stockType: 'warnList',
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
sort: "create_time", // 默认排序字段
order: "desc", // 默认排序方式
},
checkFlag: false, //检测成功标志
// 表单验证规则
formValidate: {},
//修改库存的数据
stockList: [],
//列表名称
columns: [
{
title: "商品名称",
key: "goodsName",
midwidth: 400,
tooltip: true,
},
{
title: "库存",
key: "quantity",
midwidth: 280,
render: (h, params) => {
if (params.row.quantity) {
return h("div", params.row.quantity);
} else {
return h("div", 0);
}
},
},
{
title: "预警值",
key: "alertQuantity",
midwidth: 280,
render: (h, params) => {
if (params.row.alertQuantity) {
return h("div", params.row.alertQuantity);
} else {
return h("div", 0);
}
},
},
{
title: "操作",
key: "action",
align: "center",
fixed: "right",
width: 200,
render: (h, params) => {
return h("div", [
h(
"Button",
{
props: {
type: "default",
size: "small",
},
style: {
marginRight: "5px",
},
on: {
click: () => {
this.openUpdataStockModal(params.row);
},
},
},
"库存"
),
]);
},
},
],
settingColumns: [
{
title: "商品名称",
key: "goodsName",
},
{
title: "库存",
key: "quantity",
width: 400,
render: (h, params) => {
if (params.row.quantity) {
return h("div", params.row.quantity);
} else {
return h("div", 0);
}
},
},
{
title: "预警值",
key: "alertQuantity",
width: 400,
slot: 'alertQuantitySlot',
},
],
updateStockColumns: [
{
title: "sku规格",
key: "sn",
minWidth: 120,
render: (h, params) => {
return h("div", {}, params.row.simpleSpecs);
},
},
{
title: "审核状态",
key: "authFlag",
width: 130,
render: (h, params) => {
if (params.row.authFlag == "TOBEAUDITED") {
return h("Tag", { props: { color: "blue" } }, "待审核");
} else if (params.row.authFlag == "PASS") {
return h("Tag", { props: { color: "green" } }, "通过");
} else if (params.row.authFlag == "REFUSE") {
return h("Tag", { props: { color: "red" } }, "审核拒绝");
}
},
},
{
title: "操作",
key: "action",
align: "center",
width: 200,
render: (h, params) => {
let vm = this;
return h("InputNumber", {
props: {
value: params.row.quantity,
},
on: {
"on-change": (event) => {
vm.stockList[params.index].quantity = event;
},
},
});
},
},
],
warnData: [], // 表单数据
skuAllData: [], //SKU数据
total: 0, //sku数据总数
categoryList: [], //分类列表
category: '', //选中分类
selectedSku: {},
};
},
methods: {
init() {
// 初始化数据
this.getDataList();
this.deepGroup();
},
openUpdataStockModal(row){
this.stockList = []
this.selectedSku = JSON.parse(JSON.stringify(row));
this.stockList.push(this.selectedSku);
this.updateStockModalVisible = true;
},
// 更新库存
updateStock () {
let updateStockList = this.stockList.map((i) => {
let j = { skuId: i.id, quantity: i.quantity };
return j;
});
updateGoodsSkuStocks(updateStockList).then((res) => {
if (res.success) {
this.updateStockModalVisible = false;
this.$Message.success("更新库存成功");
this.getDataList();
}
});
},
//修改预警值
updateWarnStock(row){
if(this.checkFlag){
let submit = { skuId: row.id, alertQuantity: row.alertQuantity }
updateGoodsAlertStocks(submit).then(res => {
if(res.success){
this.$Message.success('更新成功')
}
})
}
},
//检测输入值是否正确
checkVal(row){
if (
!/^[+]{0,1}(\d+)$|^[+]{0,1}(\d+\.\d+)$/.test(row.alertQuantity) ||
parseInt(row.alertQuantity) < 0 ||
parseInt(row.alertQuantity) > 99999999
) {
// 校验未通过 进行提示
this.$Message.error("请输入0~99999999之间的数字值")
row.alertQuantity = 0
this.checkFlag = false;
return;
}
this.checkFlag = true;
},
//切换分页
switchTabs(){
this.handleReset();
this.getDataList();
},
// 改变页数
changePageSize(v) {
this.searchForm.pageSize = v;
this.getDataList();
},
//改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
this.clearSelectAll();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.searchForm.categoryPath = this.category.join(",")
this.getDataList();
},
// 重置搜索条件
handleReset() {
this.searchForm = {};
this.category = [];
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
// 重新加载数据
this.getDataList();
},
// 获取商品列表数据
getDataList() {
this.loading = true;
// 带多条件搜索参数获取表单数据
if(this.stockType == 'warnList'){
//调用预警库存
getGoodsListDataByStockSeller(this.searchForm).then(res => {
if(res.success){
this.warnData = res.result.records
this.total = res.result.total
this.loading = false;
}
})
}else if(this.stockType == 'warnSetting'){
//调用获取全部sku
getGoodsSkuListDataSeller(this.searchForm).then(res => {
if(res.success){
this.skuAllData = res.result.records
this.total = res.result.total
this.loading = false;
}
})
}
},
//组织分类树
deepGroup() {
getGoodsCategoryAll().then(res =>{
if(res.success){
res.result.forEach((item) => {
let childWay = []; //第二级
// 第二层
if (item.children) {
item.children.forEach((child) => {
// // 第三层
if (child.children) {
child.children.forEach((grandson, index, arr) => {
arr[index] = {
value: grandson.id,
label: grandson.name,
children: "",
};
});
}
let children = {
value: child.id,
label: child.name,
children: child.children,
};
childWay.push(children);
});
}
// 第一层
let way = {
value: item.id,
label: item.name,
children: childWay,
};
this.categoryList.push(way);
});
}
})
},
},
mounted() {
this.init();
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/table-common.scss";
</style>

View File

@@ -148,9 +148,9 @@
title="更新库存"
v-model="updateStockModalVisible"
:mask-closable="false"
:width="500"
:width="610"
>
<Tabs value="updateStock">
<Tabs value="updateStock" v-model="updateStockType">
<TabPane label="手动规格更新" name="updateStock">
<Table
class="mt_10"
@@ -491,6 +491,7 @@ export default {
],
data: [], // 表单数据
total: 0, // 表单数据总数
updateStockType: 'updateStock', // 更新库存状态
};
},
methods: {
@@ -531,6 +532,7 @@ export default {
getGoodsSkuListDataSeller({ goodsId: id, pageSize: 1000 }).then((res) => {
if (res.success) {
this.updateStockModalVisible = true;
this.updateStockType = 'updateStock';
this.stockAllUpdate = undefined;
this.stockList = res.result.records;
}
@@ -585,21 +587,25 @@ export default {
});
},
// 更新库存
updateStock() {
let updateStockList = this.stockList.map((i) => {
let j = { skuId: i.id, quantity: i.quantity };
if (this.stockAllUpdate) {
j.quantity = this.stockAllUpdate;
}
return j;
});
updateGoodsSkuStocks(updateStockList).then((res) => {
if (res.success) {
this.updateStockModalVisible = false;
this.$Message.success("更新库存成功");
this.getDataList();
}
});
updateStock () {
if (this.updateStockType === 'updateStock' || this.updateStockType === 'stockAll') {
// updateStock 手动规格更新stockAll 批量规格更新
let updateStockList = this.stockList.map((i) => {
let j = { skuId: i.id, quantity: i.quantity };
if (this.stockAllUpdate) {
j.quantity = this.stockAllUpdate;
}
return j;
});
updateGoodsSkuStocks(updateStockList).then((res) => {
if (res.success) {
this.updateStockModalVisible = false;
this.$Message.success("更新库存成功");
this.getDataList();
}
});
}
},
// 改变页码
changePage(v) {

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
<div>
<Modal v-model="noticeFlage" :title="noticesDetail.title">
<div v-if="noticesDetail" v-html="noticesDetail.content">
<div v-if="noticesDetail" class="noticesDetail" v-html="noticesDetail.content">
</div>
</Modal>
@@ -111,12 +111,12 @@
投诉
</div>
</div>
<div class="detail-item" @click="navigateTo('goods')">
<div>
<span>{{ homeData.waitUpper || 0 }}</span>
<div>待上架</div>
<div class="detail-item" >
<div @click="navigateTo('alert-goods-quantity')">
<span>{{ homeData.alertQuantityNum || 0 }}</span>
<div>库存预警</div>
</div>
<div>
<div @click="navigateTo('goods')">
<span>{{ homeData.waitAuth || 0 }}</span>
<div>审核中</div>
</div>
@@ -294,4 +294,10 @@ export default {
</script>
<style lang="scss" scoped>
@import "./home.scss";
.noticesDetail{
/deep/ img{
max-width: 100%;
max-height: 200px;
}
}
</style>

View File

@@ -1,33 +1,24 @@
import plugins from "./plugins";
import toobar from "./toolbar";
import { upLoadFileMethods } from "@/api/common";
const localCDN = window.location.origin + "/tinymce"; //本地引入
export const initEditor = {
base_url: localCDN,
height: "400px",
language: "zh_CN",
language: "zh-Hans",
menubar: "file edit view format table", // 菜单:指定应该出现哪些菜单
toolbar: toobar, // 分组工具栏控件
plugins: plugins, // 插件(比如: advlist | link | image | preview等)
plugins:plugins, // 插件(比如: advlist | link | image | preview等)
object_resizing: false, // 是否禁用表格图片大小调整
end_container_on_empty_block: true, // enter键 分块
powerpaste_word_import: "merge", // 是否保留word粘贴样式 clean | merge
advlist_bullet_styles: "square", // 无序列表 有序列表
maxSize: "2097152", // 设置图片大小
accept: "image/jpeg, image/png", // 设置图片上传规则
images_upload_handler: async function (blobInfo, success, failure) {
const formData = new FormData();
formData.append("file", blobInfo.blob());
try {
const res = await upLoadFileMethods(formData);
if (res.result) {
success(res.result)
} else {
failure("上传文件有误请稍后重试");
}
} catch (e) {
failure('上传出错')
}
},
paste_data_images:false,
browser_spellcheck: true, // 拼写检查
branding: false, // 去水印
elementpath: false, // 禁用编辑器底部的状态栏
statusbar: false, // 隐藏编辑器底部的状态栏
// init_instance_callback: function (editor) {
// var freeTiny = document.querySelector(".tox .tox-notification--in .tox-notification .tox-notification--warning .tox .tox-notification--warning .tox-notifications-container");
// freeTiny.style.display = "none";
@@ -51,7 +42,4 @@ export const initEditor = {
ul,ol{ list-style-position:inside; }
`, // 设置样式
statusbar: false, // 隐藏编辑器底部的状态栏
elementpath: false, // 禁用编辑器底部的状态栏
paste_data_images: true, // 允许粘贴图像
};

View File

@@ -0,0 +1,130 @@
<template>
<div>
<!-- 使用 fullscreen 类来控制是否全屏显示 -->
<div :class="{ fullscreen: fullscreen }" class="tinymce-container">
<!-- 使用 tinymce-textarea 类作为编辑器的文本区域 -->
<uploadImage @callback="insertImage" />
<textarea :id="tinymceId" class="tinymce-textarea" />
</div>
</div>
</template>
<script>
import { initEditor } from "@/views/lili-components/editor/config";
import uploadImage from "@/views/lili-components/editor/upload-image.vue";
export default {
components:{uploadImage},
name: "Tinymce",
props: {
value: {
type: String,
default: "",
},
height:{
type:String,
default:'500px'
}
},
data() {
return {
// 引入编辑器的配置
initEditor,
hasChange: false, // 标记内容是否有更改
hasInit: false, // 标记编辑器是否已初始化
tinymceId:
"tinymce-" + +new Date() + ((Math.random() * 1000).toFixed(0) + ""), // 生成唯一的编辑器 ID
fullscreen: false, // 标记编辑器是否处于全屏模式
toolbar: [], // 工具栏配置
content: "", // 编辑器内容
};
},
created() {
this.init();
},
watch: {
value: {
handler(val) {
if (!this.hasChange && this.hasInit) {
// 当内容有更改且编辑器已初始化时,更新编辑器的内容
this.$nextTick(() =>
window.tinymce.get(this.tinymceId).setContent(val || "")
);
}
},
deep: true,
},
},
methods: {
// 数据返回并给富文本框插入图片
insertImage(arr){
arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img src="${v}" >`))
},
init() {
// 初始化编辑器
this.initTinymce();
},
initTinymce() {
const _this = this;
window.tinymce.init({
selector: `#${this.tinymceId}`,
convert_urls: false,
init_instance_callback: (editor) => {
if (_this.value) {
// 如果有初始值,则设置编辑器的内容为初始值
this.$nextTick(() => editor.setContent(_this.value));
}
_this.hasInit = true;
// 监听编辑器内容的变化
editor.on("NodeChange Change KeyUp SetContent", (event) => {
if (_this.value) {
// 内容发生更改
this.hasChange = true;
}
// 通过 input 事件将编辑器的内容传递给父组件
this.$emit("input", editor.getContent());
});
},
setup(editor) {
// 监听全屏状态变化
editor.on("FullscreenStateChanged", (e) => {
_this.fullscreen = e.state;
});
},
..._this.initEditor,
height:this.height
});
},
setContent(value) {
// 设置编辑器的内容
window.tinymce.get(this.tinymceId).setContent(value);
},
getContent() {
// 获取编辑器的内容
return window.tinymce.get(this.tinymceId).getContent();
},
destroyTinymce() {
const tinymce = window.tinymce.get(this.tinymceId);
if (tinymce) {
// 销毁编辑器实例
tinymce.destroy();
}
},
},
mounted() {
this.init();
},
activated() {
if (window.tinymce) {
this.initTinymce();
}
},
deactivated() {
this.destroyTinymce();
},
destroyed() {
this.destroyTinymce();
},
};
</script>

View File

@@ -1,4 +1,4 @@
const plugins = [
'advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount'
'advlist', 'anchor', 'autolink', 'autosave', 'code', 'codesample', 'directionality', 'emoticons', 'fullscreen', 'image', 'importcss', 'insertdatetime', 'link', 'lists', 'media', 'nonbreaking', 'pagebreak', 'preview', 'save', 'searchreplace', 'table', 'template', 'visualblocks', 'visualchars', 'wordcount'
]
export default plugins

View File

@@ -0,0 +1,211 @@
<template>
<div class="wrapper">
<Button @click="handleClickUploadImage">上传图片</Button>
<Modal v-model="show" width="850" @on-ok="callback" title="上传图片">
<div class="import-oss" @click="importOSS">
从资源库中导入
</div>
<div style="display: flex; flex-wrap: wrap">
<vuedraggable
:animation="200"
:list="images"
>
<div
v-for="(item, __index) in images"
:key="__index"
class="upload-list"
>
<template>
<img alt="image" :src="item.url"/>
<div class="upload-list-cover">
<div>
<Icon
size="30"
type="md-search"
@click.native="$previewImage(item.url)"
></Icon>
<Icon
size="30"
type="md-trash"
@click.native="handleRemoveGoodsPicture(__index)"
></Icon>
</div>
</div>
</template>
</div>
</vuedraggable>
<div class="upload-box">
<Upload
ref="upload"
:action="uploadFileUrl"
:format="['jpg', 'jpeg', 'png']"
:headers="{ ...accessToken }"
:max-size="10240"
:on-exceeded-size="handleMaxSize"
:on-format-error="handleFormatError"
:on-success="handleSuccessGoodsPicture"
:show-upload-list="false"
multiple
type="drag"
>
<div style="width: 148px; height: 148px; line-height: 148px">
<Icon size="20" type="md-add"></Icon>
</div>
</Upload>
</div>
</div>
</Modal>
<Modal width="1000" v-model="showOssManager" @on-ok="confirmUrls">
<OssManage ref="ossManage" @selected="(list)=>{ selectedImage = list}" @callback="handleCallback" />
</Modal>
</div>
</template>
<script>
import vuedraggable from "vuedraggable";
import {uploadFile} from "@/libs/axios";
// import OssManage from "@/views/sys/oss-manage/ossManage";
import OssManage from "@/views/shop/ossManage";
export default {
name: "upload-image",
components: {
OssManage,
vuedraggable,
},
data() {
return {
show: false, // 是否显示弹窗
uploadFileUrl: uploadFile, // 上传地址
accessToken:"",
showOssManager:false, // 是否显示oss管理弹窗
images:[],
selectedImage:[]
}
},
mounted() {
this.accessToken = {
accessToken: this.getStore("accessToken"),
};
},
methods: {
handleClickUploadImage(){
this.show = true;
},
// 回调给父级
callback() {
// 先给数据做一下处理 然后将数据传给父级
const formatImages = this.images.map((item) => item.url);
this.$emit('callback',formatImages)
},
// 移除商品图片
handleRemoveGoodsPicture(__index) {
this.images.splice(__index, 1);
},
// 图片大小不正确
handleMaxSize(file) {
this.$Notice.warning({
title: "超过文件大小限制",
desc: "图片大小不能超过10MB",
});
},
// 图片格式不正确
handleFormatError(file) {
this.$Notice.warning({
title: "文件格式不正确",
desc: "文件 " + file.name + " 的格式不正确",
});
},
// sku图片上传成功
handleSuccessGoodsPicture(res, file) {
if (file.response) {
file.url = file.response.result;
this.images.push(file);
}
},
confirmUrls(){
this.selectedImage.length ? this.selectedImage.forEach(element => {
this.images.push({ url: element.url })
}):''
this.showOssManager = false
},
handleCallback(val){
this.$Message.success("导入成功")
this.images.push({url:val.url})
},
// 从资源库中导入图片
importOSS(){
this.showOssManager = true;
this.$refs.ossManage.selectImage = true;
}
}
}
</script>
<style scoped lang="scss">
.import-oss{
margin-bottom: 10px;
text-align: right;
color: $theme_color;
cursor: pointer;
}
.wrapper{
margin: 10px 0;
}
.upload-list {
width: 150px;
height: 150px;
text-align: center;
border: 1px solid transparent;
border-radius: 4px;
display: inline-block;
background: #fff;
position: relative;
margin-right: 4px;
vertical-align: bottom;
}
.upload-box{
margin: 10px 0;
}
.upload-list img {
width: 100%;
height: 100%;
}
.upload-list-cover {
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.6);
justify-content: space-between;
align-items: center;
flex-direction: column;
}
.upload-list:hover .upload-list-cover {
display: flex;
}
.upload-list-cover div {
margin-top: 50px;
width: 100%;
>i {
width: 50%;
margin-top: 8px;
color: #fff;
font-size: 20px;
cursor: pointer;
}
}
</style>

View File

@@ -4,14 +4,14 @@
<div class="query-wrapper">
<div class="query-item">
<div>搜索范围</div>
<Input placeholder="商品名称" @on-clear="goodsData=[]; goodsParams.goodsName=''; getQueryGoodsList()" @on-enter="()=>{goodsData=[]; getQueryGoodsList();}" clearable style="width: 150px"
<Input placeholder="商品名称" @on-clear="goodsData=[]; goodsParams.goodsName=''; goodsParams.pageNumber = 1; getQueryGoodsList()" @on-enter="()=>{goodsData=[]; goodsParams.pageNumber = 1; getQueryGoodsList();}" clearable style="width: 150px"
v-model="goodsParams.goodsName" />
</div>
<div class="query-item">
<Cascader v-model="category" placeholder="请选择商品分类" style="width: 150px" :data="cateList"></Cascader>
</div>
<div class="query-item">
<Button type="primary" @click="goodsData=[]; getQueryGoodsList();" icon="ios-search">搜索</Button>
<Button type="primary" @click="goodsData=[]; goodsParams.pageNumber = 1; getQueryGoodsList();" icon="ios-search">搜索</Button>
</div>
</div>
<div >

View File

@@ -84,8 +84,8 @@ export default {
pageSize: 10, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
startDate: "", // 起始时间
endDate: "", // 终止时间
startTime: "", // 起始时间
endTime: "", // 终止时间
},
selectDate: null,
form: {
@@ -232,8 +232,8 @@ export default {
// 选择日期回调
selectDateRange(v) {
if (v) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
this.searchForm.startTime = v[0];
this.searchForm.endTime = v[1];
}
},
// 获取列表数据

View File

@@ -22,28 +22,32 @@
</div>
</div>
</vuedraggable>
<Upload
:disabled="disable"
ref="upload"
:multiple="multiple"
:show-upload-list="false"
:on-success="handleSuccess"
:on-error="handleError"
:format="['jpg','jpeg','png','gif']"
:max-size="1024"
:on-format-error="handleFormatError"
:on-exceeded-size="handleMaxSize"
:before-upload="handleBeforeUpload"
type="drag"
:action="uploadFileUrl"
:headers="accessToken"
style="display: inline-block;width:58px;"
v-if="!isView"
>
<div style="width: 58px;height:58px;line-height: 58px;">
<Icon type="md-camera" size="20"></Icon>
</div>
</Upload>
<div style="display: inline-block; width: 60px; height: 60px;border: 1px dashed #dcdee2;border-radius: 4px;line-height: 60px;text-align: center;"
@click="handleCLickImg('uploadList')">
<Icon size="20" type="md-camera"></Icon>
</div>
<!--<Upload-->
<!--:disabled="disable"-->
<!--ref="upload"-->
<!--:multiple="multiple"-->
<!--:show-upload-list="false"-->
<!--:on-success="handleSuccess"-->
<!--:on-error="handleError"-->
<!--:format="['jpg','jpeg','png','gif']"-->
<!--:max-size="1024"-->
<!--:on-format-error="handleFormatError"-->
<!--:on-exceeded-size="handleMaxSize"-->
<!--:before-upload="handleBeforeUpload"-->
<!--type="drag"-->
<!--:action="uploadFileUrl"-->
<!--:headers="accessToken"-->
<!--style="display: inline-block;width:58px;"-->
<!--v-if="!isView"-->
<!--&gt;-->
<!--<div style="width: 58px;height:58px;line-height: 58px;">-->
<!--<Icon type="md-camera" size="20"></Icon>-->
<!--</div>-->
<!--</Upload>-->
</div>
<Modal title="图片预览" v-model="viewImage" :styles="{top: '30px'}" draggable>
<img :src="imgUrl" alt="无效的图片链接" style="width: 100%;margin: 0 auto;display: block;" />
@@ -51,16 +55,22 @@
<Button @click="viewImage=false">关闭</Button>
</div>
</Modal>
<Modal width="1200px" v-model="picModalFlag" @on-ok="confirmUrls">
<ossManage @callback="callbackSelected" @selected="(list)=>{ selectedImage = list}" ref="ossManage" />
</Modal>
</div>
</template>
<script>
import { uploadFile } from "@/libs/axios";
import vuedraggable from "vuedraggable";
import ossManage from "@/views/shop/ossManage";
export default {
name: "uploadPicThumb",
components: {
vuedraggable
vuedraggable,
ossManage
},
props: {
value: { // 默认值
@@ -97,10 +107,33 @@ export default {
uploadFileUrl: uploadFile, // 上传文件
uploadList: [], // 上传文件列表
viewImage: false, // 是否预览图片
imgUrl: "" // 图片地址
imgUrl: "", // 图片地址
picModalFlag: false, // 图片选择器
selectedFormBtnName: "", // 点击图片绑定form
selectedImage: [],
};
},
methods: {
// 选择图片modal
handleCLickImg(val, index) {
this.$refs.ossManage.selectImage = true;
this.picModalFlag = true;
this.selectedFormBtnName = val;
},
// 图片选择后回调
callbackSelected(val) {
this.picModalFlag = false;
if (!this.multiple && this.uploadList && this.uploadList.length > 0) {
// 删除第一张
this.uploadList.splice(0, 1);
}
this.uploadList.push(val);
// 返回组件值
this.returnValue();
},
confirmUrls(){
},
onEnd() {
this.returnValue();
},

View File

@@ -4,12 +4,14 @@
<div>
<Button v-if="allowOperation.editPrice" @click="modifyPrice" type="primary">调整价格</Button>
<Button v-if="allowOperation.editConsignee" @click="editAddress" type="primary">修改收货地址</Button>
<Button v-if="allowOperation.showLogistics" @click="logistics" type="primary">查看物流</Button>
<Button v-if="allowOperation.showLogistics || orderPackage.length > 0" @click="checkLogistics" type="primary">查看物流</Button>
<Button @click="orderLogModal = true" type="primary">订单日志</Button>
<Button @click="printOrder" type="primary" ghost style="float:right;">打印发货单</Button>
<Button v-if="allowOperation.take" @click="orderTake" type="primary">订单核销</Button>
<Button v-if="allowOperation.ship" @click="orderDeliver" type="primary">发货</Button>
<Button v-if="allowOperation.ship" @click="groupShip" type="primary">分包裹发货</Button>
<Button @click="sfPrint" type="primary" ghost
v-if="allowOperation.showLogistics && logisticsType == 'SHUNFENG'">下载面单</Button>
<Button @click="toPrint" type="primary" ghost
@@ -338,6 +340,7 @@
<Button @click="orderLogModal = false">取消</Button>
</div>
</Modal>
<!-- 查询物流 -->
<Modal v-model="logisticsModal" width="40">
<p slot="header">
@@ -350,34 +353,64 @@
<div class="text-box">{{ sn }}</div>
</dd>
</dl>
<dl>
<dt>物流公司</dt>
<dd>
<div class="text-box">{{ logisticsInfo.shipper || orderInfo.order.logisticsName }}</div>
</dd>
</dl>
<dl>
<dt>物流单号</dt>
<dd>
<div nctype="ordersSn" class="text-box">
{{ logisticsInfo.logisticCode || orderInfo.order.logisticsNo }}
</div>
</dd>
</dl>
<div class="div-express-log">
<ul class="express-log">
<li v-for="(item, index) in logisticsInfo.traces" :key="index">
<span class="time">{{ item.AcceptTime || item.acceptTime }}</span>
<span class="detail">{{ item.AcceptStation || item.remark }}</span>
</li>
</ul>
</div>
<div v-if="packageTraceList.length > 0" v-for="(packageItem, packageIndex) in packageTraceList" :key="packageIndex">
<div class="layui-layer-wrap">
<dl>
<dt>物流公司</dt>
<dd><div class="text-box">{{ packageItem.logisticsName }}</div></dd>
</dl>
<dl>
<dt>快递单号</dt>
<dd><div nctype="ordersSn" class="text-box">{{ packageItem.logisticsNo }}</div></dd>
</dl>
<div class="div-express-log">
<ul class="express-log express-log-name">
<li v-for="(item, index) in packageItem.orderPackageItemList" :key="index">
<span class="time" style="width: 50%;"><span>商品名称</span><span>{{ item.goodsName }}</span></span>
<span class="time" style="width: 30%;"><span>发货时间</span><span>{{ item.logisticsTime }}</span></span>
<span class="time" style="width: 20%;"><span>发货数量</span><span>{{ item.deliverNumber }}</span></span>
</li>
</ul>
</div>
<div class="div-express-log">
<ul class="express-log" v-if="packageItem.traces && packageItem.traces.traces">
<li v-for="(item, index) in packageItem.traces.traces" :key="index">
<span class="time">{{ item.AcceptTime || item.acceptTime }}</span>
<span class="detail">{{ item.AcceptStation || item.remark }}</span>
</li>
</ul>
<ul class="express-log" v-else><li>暂无物流信息</li></ul>
</div>
</div>
</div>
<div v-if = "packageTraceList.length == 0 && logisticsInfo">
<div class="layui-layer-wrap">
<dl>
<dt>物流公司</dt>
<dd><div class="text-box">{{ logisticsInfo.shipper }}</div></dd>
</dl>
<dl>
<dt>快递单号</dt>
<dd><div nctype="ordersSn" class="text-box">{{ logisticsInfo.logisticCode }}</div></dd>
</dl>
<div class="div-express-log">
<ul class="express-log" v-if="logisticsInfo && logisticsInfo.traces">
<li v-for="(item, index) in logisticsInfo.traces" :key="index">
<span class="time">{{ item.AcceptTime }}</span>
<span class="detail">{{ item.AcceptStation }}</span>
</li>
</ul>
<ul class="express-log" v-else><li>暂无物流信息</li></ul>
</div>
</div>
</div>
<div slot="footer" style="text-align: right">
<Button @click="logisticsModal = false">取消</Button>
</div>
</Modal>
<!-- 订单发货 -->
<Modal v-model="orderDeliverModal" width="500px">
<p slot="header">
@@ -471,6 +504,60 @@
<Button type="primary" v-print="printInfoObj">打印发货单</Button>
</div>
</Modal>
<!--订单分包裹发货-->
<Modal v-model="groupShipModal" :loading="shipLoading" title="分包裹发快递" width="1000">
<div>
<Form ref="groupOrderDeliveryForm" :model="groupOrderDeliveryForm" :label-width="90" :rules="groupOrderDeliverFormValidate" style="position: relative">
<FormItem label="物流公司" prop="logisticsId">
<Select v-model="groupOrderDeliveryForm.logisticsId" placeholder="请选择" style="width: 250px">
<Option v-for="(item, i) in checkedLogistics" :key="i" :value="item.logisticsId">{{ item.name }}
</Option>
</Select>
</FormItem>
<FormItem label="物流单号" prop="logisticsNo">
<Input v-model="groupOrderDeliveryForm.logisticsNo" style="width: 250px" />
</FormItem>
</Form>
</div>
<Table @on-select="selectGroupShipGoodsMethods" @on-selection-change="selectGroupShipGoodsMethods"
@on-select-all="selectGroupShipGoodsMethods" :data="data" :columns="groupShipColumns" border>
<template slot="goodsSlot" slot-scope="{ row }">
<div style="margin-top: 5px; height: 80px; display: flex">
<div style="">
<img :src="row.image" style="height: 60px; margin-top: 1px; width: 60px" />
</div>
<div style="margin-left: 13px">
<div class="div-zoom">
<a @click="linkTo(row.goodsId, row.skuId)">{{
row.goodsName
}}</a>
</div>
<span v-for="(item, key) in JSON.parse(row.specs)" :key="key">
<span v-show="key != 'images'" style="font-size: 12px; color: #999999">
{{ key }} : {{ item }}
</span>
</span>
<Poptip trigger="hover" style="display: block" title="扫码在手机中查看" transfer>
<div slot="content">
<vue-qr :text="wapLinkTo(row.goodsId, row.skuId)" :margin="0" colorDark="#000" colorLight="#fff"
:size="150"></vue-qr>
</div>
<img src="../../../assets/qrcode.svg" class="hover-pointer" width="20" height="20" alt="" />
</Poptip>
</div>
</div>
</template>
<template slot="numSlot" slot-scope="{ row, index }">
<InputNumber :min="0" :max="row.___num - row.deliverNumber" v-model="data[index].canNum">
</InputNumber>
</template>
</Table>
<div slot="footer">
<Button type="default" @click="groupShipModal = false">取消</Button>
<Button type="primary" @click="confirmShipGroupGoods">确定</Button>
</div>
</Modal>
<multipleMap ref="map" @callback="getAddress"></multipleMap>
</div>
@@ -690,9 +777,112 @@ export default {
],
// 订单日志数据
orderLogData: [],
// 分包裹发货
groupShipModal: false,
shipLoading: true,
groupOrderDeliveryForm: {
logisticsNo: "", //发货单号
logisticsId: "", //物流公司
},
groupOrderDeliverFormValidate: {
logisticsNo: [{ required: true, message: "发货单号不能为空", trigger: "change" },],
logisticsId: [{ required: true, message: "请选择物流公司", trigger: "blur" },],
},
// 选择要发货的商品
selectGroupShipGoods: [],
groupShipColumns: [
{type: "selection", width: 60, align: "center",},
{title: "商品", key: "goodsName", width: 300, slot: "goodsSlot",},
{
title: "单价",
key: "unitPrice",
slot: "priceSlot",
width: 100,
render: (h, params) => {
if (!params.row.unitPrice) {
return h("div", this.$options.filters.unitPrice(0, "¥"));
}
return h("div", this.$options.filters.unitPrice(params.row.unitPrice, "¥"));
},
},
{title: "数量", key: "num", slot: "numSlot", width: 120,},
{
title: "已发包裹",
key: "deliverNumber",
render: (h, params) => {
return h("div", params.row.deliverNumber ? params.row.deliverNumber : 0);
},
},
{
title: "小计",
key: "subTotal",
width: 120,
render: (h, params) => {
return h("div", this.$options.filters.unitPrice(params.row.subTotal, "¥"));
},
},
],
orderPackage: [],
packageTraceList: []
};
},
methods: {
// 选中
selectGroupShipGoodsMethods (selected) {
this.selectGroupShipGoods = selected;
},
// 分包裹发货
groupShip () {
this.groupShipModal = true;
this.getLogisticsList();
},
// 分页获取物流公司
getLogisticsList () {
API_Order.getLogisticsChecked().then((res) => {
if (res.success) {
this.checkedLogistics = res.result;
}
});
},
// 分包裹发货
confirmShipGroupGoods () {
this.$refs.groupOrderDeliveryForm.validate(async (valid) => {
if (valid) {
if (this.selectGroupShipGoods.length) {
let submit = {
...this.groupOrderDeliveryForm,
orderSn: this.sn,
partDeliveryDTOList: this.selectGroupShipGoods.map((item) => {
return {
orderItemId: item.id,
deliveryNum: item.canNum ? item.canNum : item.num,
};
}),
};
const res = await API_Order.partDelivery(this.sn, submit);
if (res.success) {
this.$Message.success("发货成功!");
this.shipLoading = false;
this.getDataDetail();
this.getOrderPackage();
this.groupShipModal = false;
this.groupOrderDeliveryForm = []
} else {
this.shipLoading = false;
this.groupShipModal = true;
}
} else {
this.shipLoading = false;
this.groupShipModal = true;
this.$Message.error("请选择要发货的商品");
}
} else {
this.shipLoading = false;
}
});
},
// 回调地址信息
getAddress(val){
if(val.type === 'select'){
@@ -768,7 +958,16 @@ export default {
if (res.success) {
this.orderInfo = res.result;
this.allowOperation = res.result.allowOperationVO;
this.data = res.result.orderItems;
if (res.result.orderItems.length) {
this.data = res.result.orderItems.map((item) => {
return {
...item,
___num: item.num,
_disabled: item.deliverNumber >= item.num,
canNum: item.num - item.deliverNumber
};
});
}
this.orderLogData = res.result.orderLogs;
this.typeList = JSON.parse(JSON.stringify(res.result.order.priceDetailDTO.discountPriceDetail));
this.getContentPrice()
@@ -807,7 +1006,31 @@ export default {
}
});
},
getOrderPackage() {
API_Order.getPackage(this.sn).then(res => {
if (res.success) {
this.orderPackage = res.result;
console.log('this.orderPackage',this.orderPackage);
}
})
},
//查询物流
checkLogistics () {
this.logisticsModal = true;
if (this.orderPackage.length > 0) {
this.logisticsList();
} else {
this.logistics();
}
},
logisticsList () {
this.logisticsModal = true;
API_Order.getPackage(this.sn).then((res) => {
if (res.success && res.result != null) {
this.packageTraceList = res.result;
}
});
},
logistics () {
this.logisticsModal = true;
API_Order.getTraces(this.sn).then((res) => {
@@ -949,6 +1172,7 @@ export default {
this.sn = this.$route.query.sn;
this.getDataDetail();
this.getLogisticsSetting();
this.getOrderPackage();
},
// 如果是从详情页返回列表页修改列表页keepAlive为true确保不刷新页面
beforeRouteLeave (to, from, next) {
@@ -986,8 +1210,7 @@ dl dt {
}
.express-log {
margin-right: -10px;
margin: 5px;
/*margin: 5px -10px 5px 5px;*/
padding: 10px;
list-style-type: none;
@@ -1008,6 +1231,15 @@ dl dt {
}
}
.express-log-name {
li {
display: flex;
span {
display: flex;
}
}
}
.layui-layer-wrap {
dl {
border-top: solid 1px #f5f5f5;

View File

@@ -235,7 +235,7 @@ export default {
slot: "action",
align: "center",
fixed: "right",
maxWidth: 140,
maxWidth: 240,
},
],
data: [], // 表单数据

View File

@@ -43,8 +43,8 @@
@click="openOrClose(row)">关闭</Button>
<Button type="success" v-if="row.promotionStatus === 'CLOSE'" style="margin-left: 5px" size="small"
@click="openOrClose(row)">开启</Button>
<Button type="error" :disabled="row.promotionStatus == 'START'" style="margin-left: 5px" size="small"
@click="del(row)">删除</Button>
<!--<Button type="error" :disabled="row.promotionStatus == 'START'" style="margin-left: 5px" size="small"-->
<!--@click="del(row)">删除</Button>-->
</div>
</template>
</Table>

View File

@@ -77,13 +77,13 @@
@click="manage(row, 'view')"
>查看</Button
>
<Button
type="error"
size="small"
v-if="row.promotionStatus != 'START'"
@click="remove(row)"
>删除</Button
>
<!--<Button-->
<!--type="error"-->
<!--size="small"-->
<!--v-if="row.promotionStatus != 'START'"-->
<!--@click="remove(row)"-->
<!--&gt;删除</Button-->
<!--&gt;-->
<Button
type="success"
v-if="row.promotionStatus == 'CLOSE'"

View File

@@ -99,7 +99,8 @@
<script>
import changeSize from "../directives/changeSize";
import dragItem from "../directives/dragItem";
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
name: "Zone",

View File

@@ -161,7 +161,8 @@
<script>
import Draggable from "vuedraggable";
import ModelFormItem from "./modelFormItem.vue";
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
name: "modelForm",
components: {

View File

@@ -204,9 +204,7 @@
>
</div>
<div>
选择图片<Button size="small" type="primary" @click="handleSelectImg"
>选择图片</Button
>&nbsp;
选择图片<Button size="small" type="primary" @click="handleSelectImg">选择图片</Button>&nbsp;
</div>
</div>
</Modal>
@@ -218,11 +216,7 @@
></liliDialog>
<!-- 选择图片 -->
<Modal width="1200px" v-model="picModelFlag" footer-hide>
<ossManage
@callback="callbackSelected"
:isComponent="true"
ref="ossManage"
/>
<ossManage @callback="callbackSelected" :isComponent="true" ref="ossManage"/>
</Modal>
</div>
</template>
@@ -236,7 +230,8 @@ import NewGoodsSort from "./modelList/newGoodsSort.vue";
import Recommend from "./modelList/recommend.vue";
import NotEnough from "./modelList/notEnough.vue";
import Seckill from "./modelList/seckill.vue";
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
name: "modelFormItem",

View File

@@ -120,7 +120,8 @@
</template>
<script>
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
name: "modelCarousel",
props: ["data"],

View File

@@ -91,7 +91,8 @@
</template>
<script>
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
name: "modelCarousel",
props: ["data"],

View File

@@ -181,7 +181,8 @@
</template>
<script>
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
name: "modelCarousel",
props: ["data"],

View File

@@ -63,7 +63,8 @@
</div>
</template>
<script>
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
props:{
data: {

View File

@@ -139,7 +139,8 @@
</div>
</template>
<script>
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
props:{
data:{

View File

@@ -16,7 +16,7 @@
<img :src="item.img" width="210" height="210" :alt="item.name">
<p>{{item.name}}</p>
<p>
<span>{{item.price | unitPrice('¥')}}</span>
<span>{{item.price | unitPrice('¥')}}</span>
<!-- <span>{{item.price | unitPrice('¥')}}</span> -->
</p>
<div class="setup-box">
@@ -100,10 +100,10 @@ export default {
},
handleSelectGoods(item) { // 调起选择商品弹窗
if(item) this.selected = item;
this.$refs.liliDialog.open('goods', 'single')
setTimeout(() => {
this.$refs.liliDialog.goodsData = [this.selected]
}, 500);
this.$refs.liliDialog.flag = true;
this.$refs.liliDialog.goodsFlag = true;
this.$refs.liliDialog.singleGoods();
},
// 选择商品回调
selectedGoodsData(val){
@@ -175,16 +175,16 @@ export default {
cursor: pointer;
}
border-right: 1px solid #eee;
}
li:last-of-type{
border: none;
}
.curr{
p:nth-child(1){
background-color: $theme_color;
color: #fff;
}
p:nth-child(2){
@@ -223,4 +223,4 @@ export default {
}
}
}
</style>
</style>

View File

@@ -205,7 +205,8 @@
</div>
</template>
<script>
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
export default {
props: {
data: {
@@ -415,4 +416,4 @@ export default {
align-items: start;
padding: 0 30px;
}
</style>
</style>

View File

@@ -0,0 +1,729 @@
<template>
<div class="search">
<Card>
<Row @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="85" class="search-form">
<Form-item label="上传时间">
<DatePicker v-model="selectDate" type="daterange" format="yyyy-MM-dd" clearable
@on-change="selectDateRange" placeholder="选择起始时间" style="width: 200px"></DatePicker>
</Form-item>
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
</Form>
</Row>
<Row>
<div class="oss-operation padding-row">
<div>
<Upload
ref="up"
:action="commonUrl + '/common/common/upload/file'"
:data="{directoryPath: searchForm.fileDirectoryId,}"
:headers="accessToken"
:max-size="20480"
:on-error="handleError"
:on-exceeded-size="handleMaxSize"
:on-success="handleSuccess"
:show-upload-list="false"
multiple
style="display: inline-block;margin-right: 5px;"
>
<Button type="primary">上传图片</Button>
</Upload>
<Dropdown @on-click="handleDropdown">
<Button>更多操作<Icon type="md-arrow-dropdown"/></Button>
<DropdownMenu slot="list">
<DropdownItem name="refresh">刷新</DropdownItem>
<DropdownItem name="removeAll">批量删除</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
</div>
</Row>
<!--<Row >-->
<Alert show-icon>
已选择<span >{{ selectCount }}</span>
<a class="select-clear" @click="clearSelectAll">清空</a>
<span v-if="selectCount > 0" style="margin-left: 15px">共计 {{ totalSize }} 存储量</span>
</Alert>
<!--</Row>-->
<Row class="flex">
<div class="article-category mr_10">
<Tree :data="treeData" @on-contextmenu="handleContextMenu" @on-select-change="handleCateChange">
<template slot="contextMenu" v-if="!isComponent">
<DropdownItem @click.native="handleContextMenuEdit">编辑</DropdownItem>
<DropdownItem style="color: #ed4014" @click.native="handleContextMenuDelete">删除</DropdownItem>
</template>
</Tree>
<Alert v-if="!isComponent">鼠标右键编辑/删除分组</Alert>
<div class="group-row flex" v-if="!isComponent">
<Button @click="handleClickAddGroup">添加分组</Button>
</div>
</div>
<Table
ref="table"
:columns="isComponent ? viewColumns : columns"
:data="data"
:loading="loading"
border
class="table"
sortable="custom"
@on-sort-change="changeSort"
@on-selection-change="changeSelect">
<template slot="fileKey" slot-scope="{ row }">
<a @click="copyFileUrl(row)">{{ row.fileKey }}</a>
</template>
</Table>
</Row>
<Row class="mt_10" justify="end" type="flex">
<Page
:current="searchForm.pageNumber"
:page-size="searchForm.pageSize"
:page-size-opts="pageSizeOpts"
:total="total"
show-elevator
show-sizer
show-total
size="small"
@on-change="changePage"
@on-page-size-change="changePageSize"
></Page>
</Row>
</Card>
<!--查看大图-->
<Modal v-model="picVisible" :title="picTitle" draggable>
<img :src="file.url" alt="无效的图片链接" style="width: 100%; margin: 0 auto; display: block"/>
<div slot="footer">
<span>文件类型{{file.fileType}} 文件大小{{file.msize}} 创建时间{{file.createTime}}</span>
</div>
</Modal>
<!-- 添加分组修改分组编辑框 -->
<Modal v-model="enableGroup" :title="insertOrUpdate === 'insert' ? '添加分组' : '修改分组'" :loading="groupLoading" @on-ok="submitAddGroup" footer-hide>
<Form ref="formValidate" :label-width="80" :model="groupFormValidate" :rules="groupRuleValidate">
<FormItem label="所在分组" prop="id">
<Cascader v-model="groupFormValidate.id" :data="treeData" change-on-select @on-change="treeDataChange"></Cascader>
</FormItem>
<FormItem label="分组名称" prop="directoryName">
<Input v-model="groupFormValidate.directoryName"/>
</FormItem>
</Form>
<div class="modal-footer">
<Button @click="enableGroup = false">取消</Button>
<Button type="primary" @click="submitAddGroup">确定</Button>
</div>
</Modal>
</div>
</template>
<script>
import { commonUrl } from "@/libs/axios";
const config = require('@/config/index');
import { getFileListData, deleteFile, getFileDirectory, addFileDirectory, delFileDirectory, updateFileDirectory } from "@/api/index";
export default {
name: "ossManage",
data() {
return {
commonUrl, // 上传文件路径
config, // api地址
accessToken: {}, // 上传token鉴权
loading: false, // 表单加载状态
searchForm: {
// 搜索框对应data对象
name: "",
fileKey: "",
fileType: "",
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
startDate: "", // 起始时间
endDate: "", // 终止时间
},
selectDate: null, // 选择日期绑定modal
oldKey: "", // 请求参数
form: {
// 表单
name: "",
fileKey: "",
},
file: {}, // 文件数据
// 表单验证规则
formValidate: {
name: [{required: true, message: "不能为空", trigger: "blur"}],
fileKey: [{required: true, message: "不能为空", trigger: "blur"}],
},
submitLoading: false, // 添加或编辑提交状态
selectList: [], // 多选数据
selectCount: 0, // 多选计数
totalSize: "", // 文件大小统计
columns: [
// 表头
{type: "selection", width: 60, align: "center",},
{
title: "缩略图(点击预览)",
key: "url",
width: 300,
align: "center",
render: (h, params) => {
if (params.row.fileType.includes("image") > 0) {
return h("img", {
attrs: {src: params.row.url || "", alt: "加载图片失败",},
style: {cursor: "pointer", width: "80px", height: "60px", margin: "10px 0", "object-fit": "contain",},
on: {click: () => {this.showPic(params.row);},},
});
} else if (params.row.fileType.includes("video") > 0) {
// 如果视频文件大小超过5MB不予加载video
if (params.row.fileSize < 1024 * 1024 * 5) {
return h("video", {
style: {cursor: "pointer", width: "80px", height: "60px", margin: "10px 0", "object-fit": "contain",},
on: {click: () => {this.showVideo(params.row);},},
},
[h("source", {attrs: {src: params.row.url,},}),]
);
} else {
return h("img", {
attrs: {src: require("@/assets/play.png"),},
style: {cursor: "pointer", width: "80px", height: "60px", margin: "10px 0", "object-fit": "contain",},
on: {click: () => {this.showVideo(params.row);},},
});
}
} else {
return h("span", "非多媒体类型");
}
},
},
{title: "文件类型", key: "fileType", width: 115, className: this.selectImage == true ? "none" : "",},
{
title: "文件大小",
key: "fileSize",
width: 115,
sortable: true,
className: this.selectImage == true ? "none" : "",
render: (h, params) => {
let m = ((params.row.fileSize * 1.0) / (1024 * 1024)).toFixed(2) + " MB";
return h("span", m);
},
},
{
title: "上传者",
key: "createBy",
width: 200,
render: (h, params) => {
let m = "";
if (params.row.userEnums == "MANAGER") {
m = "[管理员]";
} else if (params.row.userEnums == "STORE") {
m = "[店铺]";
} else {
m = "[会员]";
}
m += params.row.createBy;
return h("span", m);
},
},
{
title: "操作",
key: "action",
align: "center",
fixed: "right",
// width: 300,
render: (h, params) => {
return h("div", [
h("Button", {
props: {type: "default", size: "small",},
style: {marginRight: "5px", display: this.selectImage === true ? "inline-block" : "none",},
on: {click: () => {this.selectedParams(params.row);},},
}, "选择"),
h("Button", {
props: {type: "info", size: "small",},
style: {marginRight: "5px", display: this.selectImage == true ? "none" : "inline-block",},
on: {click: () => {this.download(params.row);},},
}, "下载"),
h("Button", {
props: {type: "error", size: "small",},
style: {display: this.selectImage == true ? "none" : "inline-block",},
on: {click: () => {this.remove(params.row);},},
}, "删除"),
]);
},
},
],
viewColumns: [
{
title: "缩略图(点击预览)",
key: "url",
// width: 150,
align: "center",
render: (h, params) => {
if (params.row.fileType.includes("image") > 0) {
return h("img", {
attrs: {src: params.row.url || "", alt: "加载图片失败",},
style: {cursor: "pointer", width: "80px", height: "60px", margin: "10px 0", "object-fit": "contain",},
on: {click: () => {this.showPic(params.row);},},
});
} else if (params.row.fileType.includes("video") > 0) {
// 如果视频文件大小超过5MB不予加载video
if (params.row.fileSize < 1024 * 1024 * 5) {
return h("video", {
style: {cursor: "pointer", width: "80px", height: "60px", margin: "10px 0", "object-fit": "contain",},
on: {click: () => {this.showVideo(params.row);},},},
[h("source", {attrs: {src: params.row.url,},}),]
);
} else {
return h("img", {
attrs: {src: require("@/assets/play.png"),},
style: {cursor: "pointer", width: "80px", height: "60px", margin: "10px 0", "object-fit": "contain",},
on: {click: () => {this.showVideo(params.row);},},
});
}
} else {
return h("span", "非多媒体类型");
}
},
},
{title: "文件类型", key: "fileType", width: 115, className: this.selectImage == true ? "none" : "",},
{
title: "文件大小",
key: "fileSize",
width: 115,
sortable: true,
className: this.selectImage == true ? "none" : "",
render: (h, params) => {
let m = ((params.row.fileSize * 1.0) / (1024 * 1024)).toFixed(2) + " MB";
return h("span", m);
},
},
{
title: "上传者",
key: "createBy",
width: 120,
sortable: true,
render: (h, params) => {
let m = "";
if (params.row.userEnums == "MANAGER") {
m = "[管理员]";
} else if (params.row.userEnums == "STORE") {
m = "[店铺]";
} else {
m = "[会员]";
}
m += params.row.createBy;
return h("span", m);
},
},
{
title: "操作",
key: "action",
align: "center",
fixed: "right",
width: 150,
render: (h, params) => {
return h("div", [
h("Button", {
props: {type: "default", size: "small",},
style: {marginRight: "5px", display: this.selectImage === true ? "inline-block" : "none",},
on: {click: () => {this.selectedParams(params.row);},},
}, "选择")
]);
},
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
pageSizeOpts: [5, 10, 20], // 页码展示项
list: [], // 列表
//树结构
treeData: [],
treeDataDefault: [],
selectedGroupData: "",
insertOrUpdate: "insert",
groupLoading: false,
picVisible: false, // 图片modal
picTitle: "", // 图片title
enableGroup: false, // 是否展示分组
groupFormValidate: {
id: [],
level: 0,
directoryName: "",
},
groupRuleValidate: {
directoryName: [{required: true, message: "请输入分组名称", trigger: "blur",},],
id: [{required: true, message: "请选择分组", trigger: "blur", type: "array",},],
},
selectImage: false, //是否是选择
}
},
props: {
isComponent: {
default: false,
type: Boolean,
},
choose: {
type: String,
default: ""
}
},
watch: {
selectImage(val) {
if (val && !this.data.length) this.init();
},
choose(val) {
if (val) this.selectImage = val
}
},
mounted() {
if(!this.isComponent) { // 是组件的话,初始化不调用接口
this.init();
}
},
methods: {
// 初始化数据
init() {
this.accessToken = {
accessToken: this.getStore("accessToken"),
};
this.getDataList();
this.getAllList();
},
// 搜索
handleSearch() {
this.searchForm.title = this.searchForm.name;
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 5;
this.getDataList();
},
// 起止时间从新赋值
selectDateRange(v) {
if (v) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
}
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
this.clearSelectAll();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
// 排序
changeSort(e) {
this.searchForm.sort = e.key;
this.searchForm.order = e.order;
if (e.order == "normal") {
this.searchForm.order = "";
}
this.getDataList();
},
// 查看大图
showPic(v) {
this.file = v;
this.file.msize = ((v.fileSize * 1.0) / (1024 * 1024)).toFixed(2) + " MB";
this.picTitle = v.name + "(" + v.fileKey + ")";
this.picVisible = true;
},
// 选中回调
changeSelect(e) {
this.selectList = e;
this.selectCount = e.length;
let size = 0;
e.forEach((item) => {
size += item.fileSize * 1.0;
});
this.totalSize = ((size * 1.0) / (1024 * 1024)).toFixed(2) + " MB";
this.$emit("selected", e)
},
// 下载文件
download(v) {
window.open(
v.url + "?attname=&response-content-type=application/octet-stream"
);
},
// 单个删除文件
remove(v) {
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除文件 " + v.name + " ?",
loading: true,
onOk: () => {
deleteFile(v.id).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("删除文件 " + v.name + " 成功");
this.getDataList();
}
});
},
});
},
// 批量删除文件
removeAll() {
if (this.selectCount <= 0) {
this.$Message.warning("您还未选择要删除的数据");
return;
}
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除所选的 " + this.selectCount + " 个文件?",
loading: true,
onOk: () => {
let ids = "";
this.selectList.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
deleteFile(ids).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("批量删除文件成功");
this.clearSelectAll();
this.getDataList();
}
});
},
});
},
// 获取OSS资源
getDataList() {
this.pageSizeOpts = [10, 20, 50];
this.loading = true;
getFileListData(this.searchForm).then((res) => {
this.loading = false;
this.data = res.result.records;
this.total = res.result.total;
});
},
// 上传文件超过大小限制
handleMaxSize(file) {
this.$Notice.warning({
title: "文件大小过大",
desc: "所选文件大小过大, 不得超过 1M.",
});
},
// 上传成功回调
handleSuccess(res, file) {
if (res.success) {
this.$Message.success("上传文件 " + file.name + " 成功");
this.getDataList();
} else {
this.$Message.error(res.message);
}
},
// 上传失败回调
handleError(error, file, fileList) {
this.$Message.error(error.toString());
},
// 清除选中状态
clearSelectAll() {
this.$refs.table.selectAll(false);
this.totalSize = "";
},
// 更多操作
handleDropdown(name) {
if (name === "refresh") {
this.getDataList();
} else if (name === "removeAll") {
this.removeAll();
}
},
handleContextMenu(val) {
this.selectedGroupData = val;
},
// 编辑分组
handleContextMenuEdit(val) {
this.insertOrUpdate = "update";
this.enableGroup = true;
// this.groupFormValidate = this.selectedGroupData;
this.groupFormValidate.directoryName = this.selectedGroupData.title;
this.groupFormValidate.id = [this.selectedGroupData.value];
this.groupFormValidate.level = this.selectedGroupData.level;
this.groupFormValidate.parentId = this.selectedGroupData.parentId;
},
// 删除分组
async handleContextMenuDelete(val) {
this.$Modal.confirm({
title: "提示",
content: "是否删除该分组",
onOk: async () => {
const res = await delFileDirectory(this.selectedGroupData.value);
if (res.success) {
this.$Message.success("删除成功!");
this.getAllList();
}
},
});
},
// 选择分类回调
handleCateChange(data) {
this.selectedGroupData = data[0];
let {value, type, level} = data[0];
this.list.push({value, type, level});
this.searchForm.fileDirectoryId = value;
if (value === "0" || value === 0) {
delete this.searchForm.fileDirectoryId;
this.groupFormValidate.level = 0;
} else {
this.groupFormValidate.level = Number(level) + 1;
}
this.searchForm.userEnums = type;
this.getDataList();
},
treeDataChange(value, selectedData) {
if (value && value.length) {
if (value[value.length -1] == '0') {
this.groupFormValidate.level = 0;
} else {
this.groupFormValidate.level = Number(selectedData[selectedData.length -1].level) + 1;
}
}
},
// 保存/修改分组
async submitAddGroup() {
this.$refs["formValidate"].validate(async (valid) => {
if (valid) {
let res;
const params = { ...this.groupFormValidate };
if (this.insertOrUpdate === "insert") {
// params.directoryType = this.selectedGroupData.directoryType
params.parentId = params.id[params.id.length - 1];
// params.type = this.selectedGroupData.type
delete params.id;
res = await addFileDirectory(params);
} else {
params.id = params.id[params.id.length - 1];
res = await updateFileDirectory(params);
}
if (res.success) {
this.$Message.success("操作成功!");
this.enableGroup = false;
this.getAllList();
}
this.$Modal.remove();
} else {
this.$Message.error("请填写完整信息!");
}
});
},
// 添加/修改分组
handleClickAddGroup() {
this.insertOrUpdate = "insert";
if (this.selectedGroupData) {
this.groupFormValidate.id = [this.selectedGroupData.value];
} else {
this.groupFormValidate.id = ["0"];
}
this.enableGroup = true;
this.groupFormValidate.directoryName = "";
},
copyFileUrl(row) {
const textArea = document.createElement("textarea");
textArea.value = row.url;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand("copy");
this.$Message.success("复制成功");
} catch (err) {
console.error("Unable to copy to clipboard", err);
}
document.body.removeChild(textArea);
},
// 获取全部文件目录
getAllList(parent_id) {
this.loading = true;
getFileDirectory(parent_id).then((res) => {
this.loading = false;
if (res.success) {
this.treeData = this.getTree(res.result);
this.treeDataDefault = this.getTree(res.result);
this.treeData.unshift({
title: "全部图片",
label: "全部分类",
value: "0",
level: 0,
children: [],
id: "0",
categoryId: 0,
});
}
});
},
// 文件目录分类格式化方法
getTree(tree = []) {
let arr = [];
if (!!tree && tree.length !== 0) {
tree.forEach((item) => {
let obj = {};
obj.title = item.directoryName;
obj.value = item.id; // 拥有者id
obj.type = item.directoryType; // 用户类型
obj.label = item.directoryName;
obj.level = item.level;
obj.expand = false;
obj.selected = false;
obj.contextmenu = true;
obj.parentId = item.parentId;
obj.children = this.getTree(item.children); // 递归调用
arr.push(obj);
});
}
return arr;
},
/**
* 选择
*/
selectedParams(val) {
this.$emit("callback", val);
},
}
}
</script>
<style lang="scss">
// 建议引入通用样式 可删除下面样式代码
@import "@/styles/table-common.scss";
.export {
margin: 10px 20px 10px 0;
}
.group-row {
padding-top: 10px;
border-top: 1px solid #ededed;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: center;
> * {
margin-right: 10px;
}
}
.article-category {
flex: 2;
min-width: 200px;
}
.table {
flex: 11;
}
.ivu-card {
width: 100%;
}
.modal-footer {
text-align: center;
> * {
margin: 0 10px;
}
}
</style>

View File

@@ -294,6 +294,7 @@ export default {
this.operation = "INFO";
this.currentTab = "INFO";
this.getData();
this.$Message.success("刷新成功");
},
//运费模板数据
getData() {

View File

@@ -226,7 +226,8 @@
</div>
</template>
<script>
import ossManage from "@/views/sys/oss-manage/ossManage";
// import ossManage from "@/views/sys/oss-manage/ossManage";
import ossManage from "@/views/shop/ossManage";
import hotzone from "@/views/shop/hotzone";
import { modelData } from "./config";
import ways from "@/views/lili-dialog/wap.js"; // 选择链接的类型

View File

@@ -168,9 +168,7 @@ export default {
// 返回查询数据页面
goback() {
this.$router.push({
path: "/wapList",
});
this.$router.go(-1);
},
// 保存

View File

@@ -804,6 +804,7 @@ export default {
size += item.fileSize * 1.0;
});
this.totalSize = ((size * 1.0) / (1024 * 1024)).toFixed(2) + " MB";
this.$emit('selected',e)
},
},
mounted() {