mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2025-12-20 09:55:53 +08:00
commit message
This commit is contained in:
206
seller/src/views/Main.vue
Normal file
206
seller/src/views/Main.vue
Normal file
@@ -0,0 +1,206 @@
|
||||
<style lang="scss" scoped>
|
||||
@import "./main.scss";
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="sidebar-menu-con menu-bar">
|
||||
<div class="logo-con">
|
||||
<img src="../assets/logo.png" key="max-logo" />
|
||||
</div>
|
||||
<shrinkable-menu></shrinkable-menu>
|
||||
</div>
|
||||
<!-- 顶部标题栏主体 -->
|
||||
<div class="main-header-con" style="padding-left:240px">
|
||||
<div class="main-header">
|
||||
<div :class="{'header-avator-con':navType!=4, 'header-avator-con nav4':navType == 4}">
|
||||
<!-- 用户头像 -->
|
||||
<div class="user-dropdown-menu-con">
|
||||
<Row type="flex" justify="end" align="middle" class="user-dropdown-innercon">
|
||||
<Dropdown transfer trigger="hover" @on-click="handleClickUserDropdown">
|
||||
<div class="dropList">
|
||||
<span class="main-user-name">{{ userInfo.storeName }}</span>
|
||||
<Icon type="md-arrow-dropdown" />
|
||||
<Avatar :src="userInfo.storeLogo" style="background: #fff;margin-left: 10px;"></Avatar>
|
||||
</div>
|
||||
<DropdownMenu slot="list">
|
||||
<!-- <DropdownItem name="ownSpace">{{ $t('userCenter') }}</DropdownItem> -->
|
||||
<DropdownItem name="changePass">{{ $t('changePass') }}</DropdownItem>
|
||||
<DropdownItem name="loginOut" divided>{{ $t('logout') }}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 已打开的页面标签 -->
|
||||
<div class="tags-con">
|
||||
<tags-page-opened :pageTagsList="pageTagsList"></tags-page-opened>
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-page-con">
|
||||
<div class="single-page">
|
||||
<keep-alive :include="cachePage">
|
||||
<router-view></router-view>
|
||||
</keep-alive>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 全局加载动画 -->
|
||||
<circleLoading class="loading-position" v-show="loading" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import shrinkableMenu from "./main-components/shrinkable-menu/shrinkable-menu.vue";
|
||||
import tagsPageOpened from "./main-components/tags-page-opened.vue";
|
||||
import breadcrumbNav from "./main-components/breadcrumb-nav.vue";
|
||||
import fullScreen from "./main-components/fullscreen.vue";
|
||||
import messageTip from "./main-components/message-tip.vue";
|
||||
import circleLoading from "@/views/my-components/lili/circle-loading.vue";
|
||||
import Cookies from "js-cookie";
|
||||
import util from "@/libs/util.js";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
shrinkableMenu,
|
||||
tagsPageOpened,
|
||||
breadcrumbNav,
|
||||
fullScreen,
|
||||
messageTip,
|
||||
circleLoading,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sliceNum: 5, // 展示nav数量
|
||||
userInfo: "", // 用户信息
|
||||
navType: 1, // nav类型
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$store.state.app.loading;
|
||||
},
|
||||
pageTagsList() {
|
||||
return this.$store.state.app.storeOpenedList; // 打开的页面的页面对象
|
||||
},
|
||||
cachePage() {
|
||||
return this.$store.state.app.cachePage;
|
||||
},
|
||||
lang() {
|
||||
return this.$store.state.app.lang;
|
||||
},
|
||||
mesCount() {
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// 菜单
|
||||
let pathArr = util.setCurrentPath(this, this.$route.name);
|
||||
if (pathArr.length >= 2) {
|
||||
this.$store.commit("addOpenSubmenu", pathArr[1].name);
|
||||
}
|
||||
|
||||
let userInfo = JSON.parse(Cookies.get("userInfo"));
|
||||
this.userInfo = userInfo;
|
||||
this.checkTag(this.$route.name);
|
||||
|
||||
let currWidth = document.body.clientWidth;
|
||||
if (currWidth <= 1200) {
|
||||
this.sliceNum = 2;
|
||||
}
|
||||
},
|
||||
selectNav(name) {
|
||||
this.$store.commit("setCurrNav", name);
|
||||
this.setStore("currNav", name);
|
||||
// 清空所有已打开标签
|
||||
// this.$store.commit("clearAllTags");
|
||||
if (this.$route.name != "home_index") {
|
||||
this.$router.push({
|
||||
name: "home_index",
|
||||
});
|
||||
}
|
||||
util.initRouter(this);
|
||||
},
|
||||
toggleClick() {
|
||||
this.shrink = !this.shrink;
|
||||
},
|
||||
handleLanDropdown(name) {
|
||||
this.$i18n.locale = name;
|
||||
this.$store.commit("switchLang", name);
|
||||
},
|
||||
handleClickUserDropdown(name) {
|
||||
if (name == "ownSpace") {
|
||||
util.openNewPage(this, "personal-enter");
|
||||
this.$router.push({
|
||||
name: "personal-enter",
|
||||
});
|
||||
} else if (name == "changePass") {
|
||||
util.openNewPage(this, "change_pass");
|
||||
this.$router.push({
|
||||
name: "change_pass",
|
||||
});
|
||||
} else if (name == "loginOut") {
|
||||
Cookies.set("accessToken", "");
|
||||
this.$store.commit("logout", this);
|
||||
this.$store.commit("clearOpenedSubmenu");
|
||||
this.setStore("accessToken", "");
|
||||
this.setStore("refreshToken", "");
|
||||
this.$router.push({ path: "/login" });
|
||||
}
|
||||
},
|
||||
checkTag(name) {
|
||||
let openpageHasTag = this.pageTagsList.some((item) => {
|
||||
if (item.name == name) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!openpageHasTag) {
|
||||
// 解决关闭当前标签后再点击回退按钮会退到当前页时没有标签的问题
|
||||
util.openNewPage(
|
||||
this,
|
||||
name,
|
||||
this.$route.params || {},
|
||||
this.$route.query || {}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
resize() {
|
||||
let currWidth = document.body.clientWidth;
|
||||
let count = currWidth / 300;
|
||||
if (count > 6) {
|
||||
this.sliceNum = 6;
|
||||
} else {
|
||||
this.sliceNum = count;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
$route(to) {
|
||||
this.$store.commit("setCurrentPageName", to.name);
|
||||
let pathArr = util.setCurrentPath(this, to.name);
|
||||
if (pathArr.length > 2) {
|
||||
this.$store.commit("addOpenSubmenu", pathArr[1].name);
|
||||
}
|
||||
this.checkTag(to.name);
|
||||
localStorage.currentPageName = to.name;
|
||||
},
|
||||
lang() {
|
||||
util.setCurrentPath(this, this.$route.name); // 在切换语言时用于刷新面包屑
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
let that = this;
|
||||
this.resize();
|
||||
window.addEventListener("resize", function () {
|
||||
that.resize();
|
||||
});
|
||||
},
|
||||
created() {
|
||||
// 显示打开的页面的列表
|
||||
this.$store.commit("setOpenedList");
|
||||
},
|
||||
};
|
||||
</script>
|
||||
19
seller/src/views/change-password/change-password.scss
Normal file
19
seller/src/views/change-password/change-password.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
.change-pass {
|
||||
&-btn-box {
|
||||
margin-bottom: 10px;
|
||||
|
||||
button {
|
||||
padding-left: 0;
|
||||
|
||||
span {
|
||||
color: #2D8CF0;
|
||||
transition: all .2s;
|
||||
}
|
||||
|
||||
span:hover {
|
||||
color: #0C25F1;
|
||||
transition: all .2s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
175
seller/src/views/change-password/change-password.vue
Normal file
175
seller/src/views/change-password/change-password.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div>
|
||||
<Card class="change-pass">
|
||||
<p slot="title">
|
||||
<Icon type="key"></Icon>修改密码
|
||||
</p>
|
||||
<div>
|
||||
<Form
|
||||
ref="editPasswordForm"
|
||||
:model="editPasswordForm"
|
||||
:label-width="100"
|
||||
label-position="right"
|
||||
:rules="passwordValidate"
|
||||
style="width:450px"
|
||||
>
|
||||
<FormItem label="原密码" prop="oldPass">
|
||||
<Input type="password" v-model="editPasswordForm.oldPass" placeholder="请输入现在使用的密码"></Input>
|
||||
</FormItem>
|
||||
<FormItem label="新密码" prop="newPassword">
|
||||
<SetPassword style="width:350px;" v-model="editPasswordForm.newPassword" @on-change="changeInputPass" />
|
||||
</FormItem>
|
||||
<FormItem label="确认新密码" prop="rePass">
|
||||
<Input type="password" v-model="editPasswordForm.rePass" placeholder="请再次输入新密码"></Input>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button
|
||||
type="primary"
|
||||
style="width: 100px;margin-right:5px"
|
||||
:loading="savePassLoading"
|
||||
@click="saveEditPass"
|
||||
>保存</Button>
|
||||
<Button @click="cancelEditPass">取消</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SetPassword from "@/views/my-components/lili/set-password";
|
||||
import { changePass } from "@/api/index";
|
||||
export default {
|
||||
name: "change_pass",
|
||||
components: {
|
||||
SetPassword
|
||||
},
|
||||
data() {
|
||||
const valideRePassword = (rule, value, callback) => {
|
||||
if (value !== this.editPasswordForm.newPassword) {
|
||||
callback(new Error("两次输入密码不一致"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
savePassLoading: false, // 保存loading
|
||||
editPasswordForm: { // 修改密码表单
|
||||
oldPass: "", // 旧密码
|
||||
newPassword: "", // 新密码
|
||||
rePass: "" // 从新输入新密码
|
||||
},
|
||||
strength: "", // 密码强度
|
||||
passwordValidate: {
|
||||
oldPass: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入原密码",
|
||||
trigger: "blur"
|
||||
}
|
||||
],
|
||||
newPassword: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入新密码",
|
||||
trigger: "blur"
|
||||
},
|
||||
{
|
||||
min: 6,
|
||||
message: "请至少输入6个字符",
|
||||
trigger: "blur"
|
||||
},
|
||||
{
|
||||
max: 32,
|
||||
message: "最多输入32个字符",
|
||||
trigger: "blur"
|
||||
}
|
||||
],
|
||||
rePass: [
|
||||
{
|
||||
required: true,
|
||||
message: "请再次输入新密码",
|
||||
trigger: "blur"
|
||||
},
|
||||
{
|
||||
validator: valideRePassword,
|
||||
trigger: "blur"
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
changeInputPass(v, grade, strength) {
|
||||
this.strength = strength;
|
||||
},
|
||||
saveEditPass() {
|
||||
let params = {
|
||||
password: this.md5(this.editPasswordForm.oldPass),
|
||||
newPassword: this.md5(this.editPasswordForm.newPassword)
|
||||
};
|
||||
this.$refs["editPasswordForm"].validate(valid => {
|
||||
if (valid) {
|
||||
this.savePassLoading = true;
|
||||
changePass(params).then(res => {
|
||||
this.savePassLoading = false;
|
||||
if (res.success) {
|
||||
this.$Modal.success({
|
||||
title: "修改密码成功",
|
||||
content: "修改密码成功,需重新登录",
|
||||
onOk: () => {
|
||||
this.$store.commit("logout", this);
|
||||
this.$store.commit("clearOpenedSubmenu");
|
||||
this.$router.push({
|
||||
name: "login"
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
cancelEditPass() {
|
||||
this.$store.commit("removeTag", "change_pass");
|
||||
localStorage.storeOpenedList = JSON.stringify(
|
||||
this.$store.state.app.storeOpenedList
|
||||
);
|
||||
let lastPageName = "";
|
||||
let length = this.$store.state.app.storeOpenedList.length;
|
||||
if (length > 1) {
|
||||
lastPageName = this.$store.state.app.storeOpenedList[length - 1].name;
|
||||
} else {
|
||||
lastPageName = this.$store.state.app.storeOpenedList[0].name;
|
||||
}
|
||||
this.$router.push({
|
||||
name: lastPageName
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.change-pass {
|
||||
&-btn-box {
|
||||
margin-bottom: 10px;
|
||||
|
||||
button {
|
||||
padding-left: 0;
|
||||
|
||||
span {
|
||||
color: #2d8cf0;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
span:hover {
|
||||
color: #0c25f1;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
49
seller/src/views/distribution/dataJson.js
Normal file
49
seller/src/views/distribution/dataJson.js
Normal file
@@ -0,0 +1,49 @@
|
||||
// 分销商状态列表
|
||||
export const distributionStatusList= [
|
||||
{
|
||||
value:'APPLY',
|
||||
label:'申请中'
|
||||
},
|
||||
{
|
||||
value:'RETREAT',
|
||||
label:'已清退'
|
||||
},
|
||||
{
|
||||
value:'REFUSE',
|
||||
label:'审核拒绝'
|
||||
},
|
||||
{
|
||||
value:'PASS',
|
||||
label:'审核通过'
|
||||
},
|
||||
]
|
||||
// 分销佣金状态列表
|
||||
export const cashStatusList = [
|
||||
{
|
||||
value:'APPLY',
|
||||
label:'待处理'
|
||||
},
|
||||
{
|
||||
value:'REFUSE',
|
||||
label:'拒绝'
|
||||
},
|
||||
{
|
||||
value:'PASS',
|
||||
label:'通过'
|
||||
}
|
||||
]
|
||||
// 分销订单状态列表
|
||||
export const orderStatusList = [
|
||||
{
|
||||
value:'WAIT_BILL',
|
||||
label:'待结算'
|
||||
},
|
||||
{
|
||||
value:'WAIT_CASH',
|
||||
label:'待提现'
|
||||
},
|
||||
{
|
||||
value:'COMPLETE_CASH',
|
||||
label:'提现完成'
|
||||
}
|
||||
]
|
||||
311
seller/src/views/distribution/distributionGoods.vue
Normal file
311
seller/src/views/distribution/distributionGoods.vue
Normal file
@@ -0,0 +1,311 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<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="店铺名称">
|
||||
<Select v-model="searchForm.shopId" placeholder="请选择" @on-query-change="searchChange" filterable clearable style="width: 200px">
|
||||
<Option v-for="item in shopList" :value="item.id" :key="item.id">{{ item.storeName }}</Option>
|
||||
</Select>
|
||||
</Form-item> -->
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="operation padding-row">
|
||||
<Button @click="add" type="primary">添加</Button>
|
||||
<!-- <Button @click="add" type="default">批量删除</Button>-->
|
||||
</Row>
|
||||
<Row>
|
||||
<Table :loading="loading" border :columns="columns" :data="data" ref="table" sortable="custom" @on-sort-change="changeSort" @on-selection-change="changeSelect">
|
||||
<!-- 商品栏目格式化 -->
|
||||
<template slot="goodsSlot" slot-scope="scope">
|
||||
<div style="margin-top: 5px;height: 70px; display: flex;">
|
||||
<div style="">
|
||||
<img :src="scope.row.thumbnail" style="height: 60px;margin-top: 3px;width: 60px">
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 13px;">
|
||||
<div class="div-zoom" >
|
||||
<a>{{scope.row.goodsName}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
<liliDialog
|
||||
ref="liliDialog"
|
||||
@selectedGoodsData="selectedGoodsData"
|
||||
></liliDialog>
|
||||
<Modal
|
||||
:title="modalTitle"
|
||||
v-model="modalVisible"
|
||||
:mask-closable="false"
|
||||
:width="500"
|
||||
>
|
||||
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
|
||||
<FormItem label="分销佣金" prop="commission">
|
||||
<Input v-model="form.commission" clearable style="width: 100%"/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="modalVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
|
||||
>提交
|
||||
</Button
|
||||
>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getDistributionGoods,
|
||||
distributionGoodsCancel,
|
||||
distributionGoodsCheck
|
||||
} from "@/api/distribution";
|
||||
import liliDialog from "../lili-dialog/index";
|
||||
|
||||
import {getShopListData} from '@/api/shops'
|
||||
export default {
|
||||
name: "distributionGoods",
|
||||
components: {
|
||||
liliDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
modalTitle: "", // 添加或编辑标题
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
shopList:[], // 店铺列表
|
||||
loading: true, // 表单加载状态
|
||||
drop: false,
|
||||
dropDownContent: "展开",
|
||||
dropDownIcon: "ios-arrow-down",
|
||||
searchForm: { // 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
selectList: [], // 多选数据
|
||||
form:{
|
||||
commission : 1 // 分销金额
|
||||
},
|
||||
skuId:0, // 当前分销商品的skuId
|
||||
formValidate: {
|
||||
commission: [
|
||||
{ required: true, message: '请输入大于1小于9999的合法分销金额'},
|
||||
{
|
||||
pattern: /^[1-9]\d{0,3}(\.\d{1,2})?$/,
|
||||
message: "请输入大于1小于9999的合法分销金额",
|
||||
trigger: "change"
|
||||
}],
|
||||
},
|
||||
columns: [ // 表哥表头
|
||||
{
|
||||
type: "selection",
|
||||
width: 60,
|
||||
align: "center"
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 250,
|
||||
slot: "goodsSlot",
|
||||
},
|
||||
{
|
||||
title: "商品价格",
|
||||
key: "price",
|
||||
width: 130,
|
||||
render: (h, params) => {
|
||||
return h("div", this.$options.filters.unitPrice(params.row.price,'¥'));
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "库存",
|
||||
key: "quantity",
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: "店铺名称",
|
||||
key: "storeName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "佣金金额",
|
||||
key: "commission",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
if(params.row.commission !=null){
|
||||
return h("div", this.$options.filters.unitPrice(params.row.commission,'¥'));
|
||||
}else{
|
||||
return h("div", this.$options.filters.unitPrice(0,'¥'));
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 150,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "error",
|
||||
size: "small"
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.remove(params.row);
|
||||
}
|
||||
}
|
||||
},
|
||||
"删除"
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0 // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
// this.getShopList()
|
||||
},
|
||||
selectedGoodsData(v){
|
||||
this.modalVisible = true
|
||||
this.form.commission = 1
|
||||
this.modalTitle = "保存分销商品"
|
||||
this.skuId = v[0].id
|
||||
//this.data.unshift(v[0])
|
||||
},
|
||||
add(){
|
||||
|
||||
this.$refs.liliDialog.flag = true;
|
||||
this.$refs.liliDialog.goodsFlag = true;
|
||||
|
||||
this.$refs.liliDialog.singleGoods();
|
||||
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
handleSubmit(){
|
||||
this.$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
distributionGoodsCheck(this.skuId,this.form).then(res => {
|
||||
if(res.message === 'success') {
|
||||
this.$Message.success("添加成功");
|
||||
}
|
||||
this.modalVisible = false
|
||||
this.getDataList()
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
// 带多条件搜索参数获取表单数据 请自行修改接口
|
||||
getDistributionGoods(this.searchForm).then(res => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
// 记得确认修改此处
|
||||
content: "您确认要删除此分销商品么?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
// 删除
|
||||
distributionGoodsCancel(v.id).then(res => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getShopList (val) {
|
||||
const params = {
|
||||
pageNumber:1,
|
||||
pageSize:10,
|
||||
storeName:''
|
||||
}
|
||||
if (val) {
|
||||
params.storeName = val;
|
||||
} else {
|
||||
params.storeName = ''
|
||||
}
|
||||
|
||||
getShopListData(params).then(res => {
|
||||
this.shopList = res.result.records
|
||||
})
|
||||
},
|
||||
searchChange(val){
|
||||
this.getShopList(val)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/table-common.scss";
|
||||
.search-form{
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
128
seller/src/views/error-page/403.vue
Normal file
128
seller/src/views/error-page/403.vue
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
<template>
|
||||
<div class="error403">
|
||||
<div class="error403-body-con">
|
||||
<Card>
|
||||
<div class="error403-body-con-title">4<span class="error403-0-span">
|
||||
<Icon type="android-lock"></Icon>
|
||||
</span><span class="error403-key-span">
|
||||
<Icon size="220" type="ios-bolt"></Icon>
|
||||
</span></div>
|
||||
<p class="error403-body-con-message">You don't have permission</p>
|
||||
<div class="error403-btn-con">
|
||||
<Button @click="goHome" size="large" style="width: 200px;" type="text">返回首页</Button>
|
||||
<Button @click="backPage" size="large" style="width: 200px;margin-left: 40px;" type="primary">返回上一页</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Error403",
|
||||
methods: {
|
||||
backPage() {
|
||||
this.$router.go(-1);
|
||||
},
|
||||
goHome() {
|
||||
this.$router.push({
|
||||
name: "home_index",
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@keyframes error403animation {
|
||||
0% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
40% {
|
||||
transform: rotateZ(-20deg);
|
||||
}
|
||||
45% {
|
||||
transform: rotateZ(-15deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotateZ(-20deg);
|
||||
}
|
||||
55% {
|
||||
transform: rotateZ(-15deg);
|
||||
}
|
||||
60% {
|
||||
transform: rotateZ(-20deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
.error403 {
|
||||
&-body-con {
|
||||
width: 700px;
|
||||
height: 500px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
&-title {
|
||||
text-align: center;
|
||||
font-size: 240px;
|
||||
font-weight: 700;
|
||||
color: #2d8cf0;
|
||||
height: 260px;
|
||||
line-height: 260px;
|
||||
margin-top: 40px;
|
||||
.error403-0-span {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 170px;
|
||||
height: 170px;
|
||||
border-radius: 50%;
|
||||
border: 20px solid #ed3f14;
|
||||
color: #ed3f14;
|
||||
margin-right: 10px;
|
||||
i {
|
||||
display: inline-block;
|
||||
font-size: 120px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
.error403-key-span {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 190px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
i {
|
||||
display: inline-block;
|
||||
font-size: 190px;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
transform: translate(-50%, -60%);
|
||||
transform-origin: center bottom;
|
||||
animation: error403animation 2.8s ease 0s infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-message {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 4px;
|
||||
color: #dddde2;
|
||||
}
|
||||
}
|
||||
&-btn-con {
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
91
seller/src/views/error-page/404.vue
Normal file
91
seller/src/views/error-page/404.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
<template>
|
||||
<div class="error404">
|
||||
<div class="error404-body-con">
|
||||
<Card>
|
||||
<div class="error404-body-con-title">4<span><Icon type="ios-navigate-outline"></Icon></span>4</div>
|
||||
<p class="error404-body-con-message">YOU LOOK LOST</p>
|
||||
<div class="error404-btn-con">
|
||||
<Button @click="goHome" size="large" style="width: 200px;" type="text">返回首页</Button>
|
||||
<Button @click="backPage" size="large" style="width: 200px;margin-left: 40px;" type="primary">返回上一页</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Error404',
|
||||
methods: {
|
||||
backPage () {
|
||||
this.$router.go(-1);
|
||||
},
|
||||
goHome () {
|
||||
this.$router.push({
|
||||
name: 'home_index'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@keyframes error404animation {
|
||||
0% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
20% {
|
||||
transform: rotateZ(-60deg);
|
||||
}
|
||||
40% {
|
||||
transform: rotateZ(-10deg);
|
||||
}
|
||||
60% {
|
||||
transform: rotateZ(50deg);
|
||||
}
|
||||
80% {
|
||||
transform: rotateZ(-20deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
.error404{
|
||||
&-body-con{
|
||||
width: 700px;
|
||||
height: 500px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
&-title{
|
||||
text-align: center;
|
||||
font-size: 240px;
|
||||
font-weight: 700;
|
||||
color: #2d8cf0;
|
||||
height: 260px;
|
||||
line-height: 260px;
|
||||
margin-top: 40px;
|
||||
span{
|
||||
display: inline-block;
|
||||
color: #19be6b;
|
||||
font-size: 230px;
|
||||
animation: error404animation 3s ease 0s infinite alternate;
|
||||
}
|
||||
}
|
||||
&-message{
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 12px;
|
||||
color: #dddde2;
|
||||
}
|
||||
}
|
||||
&-btn-con{
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
107
seller/src/views/error-page/500.vue
Normal file
107
seller/src/views/error-page/500.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
|
||||
<template>
|
||||
<div class="error500">
|
||||
<div class="error500-body-con">
|
||||
<Card>
|
||||
<div class="error500-body-con-title">
|
||||
5<span class="error500-0-span"><Icon type="social-freebsd-devil"></Icon></span><span class="error500-0-span"><Icon type="social-freebsd-devil"></Icon></span>
|
||||
</div>
|
||||
<p class="error500-body-con-message">Oops! the server is wrong</p>
|
||||
<div class="error500-btn-con">
|
||||
<Button @click="goHome" size="large" style="width: 200px;" type="text">返回首页</Button>
|
||||
<Button @click="backPage" size="large" style="width: 200px;margin-left: 40px;" type="primary">返回上一页</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Error500',
|
||||
methods: {
|
||||
backPage () {
|
||||
this.$router.go(-1);
|
||||
},
|
||||
goHome () {
|
||||
this.$router.push({
|
||||
name: 'home_index'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@keyframes error500animation {
|
||||
0% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
20% {
|
||||
transform: rotateZ(-10deg);
|
||||
}
|
||||
40% {
|
||||
transform: rotateZ(5deg);
|
||||
}
|
||||
60% {
|
||||
transform: rotateZ(-5deg);
|
||||
}
|
||||
80% {
|
||||
transform: rotateZ(10deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
.error500{
|
||||
&-body-con{
|
||||
width: 700px;
|
||||
height: 500px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
&-title{
|
||||
text-align: center;
|
||||
font-size: 240px;
|
||||
font-weight: 700;
|
||||
color: #2d8cf0;
|
||||
height: 260px;
|
||||
line-height: 260px;
|
||||
margin-top: 40px;
|
||||
.error500-0-span{
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 170px;
|
||||
height: 170px;
|
||||
border-radius: 50%;
|
||||
border: 20px solid #ed3f14;
|
||||
color: #ed3f14;
|
||||
margin-right: 10px;
|
||||
i{
|
||||
display: inline-block;
|
||||
font-size: 120px;
|
||||
position: absolute;
|
||||
bottom: -10px;
|
||||
left: 10px;
|
||||
transform-origin: center bottom;
|
||||
animation: error500animation 3s ease 0s infinite alternate;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-message{
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 4px;
|
||||
color: #dddde2;
|
||||
}
|
||||
}
|
||||
&-btn-con{
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
323
seller/src/views/goods/goods-manage/category.vue
Normal file
323
seller/src/views/goods/goods-manage/category.vue
Normal file
@@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<Card>
|
||||
<div class="operation">
|
||||
<Button @click="addParent">添加一级分类</Button>
|
||||
<Button @click="refresh">刷新列表</Button>
|
||||
</div>
|
||||
<tree-table
|
||||
ref="treeTable"
|
||||
size="default"
|
||||
:loading="loading"
|
||||
:data="tableData"
|
||||
|
||||
:columns="columns"
|
||||
:border="true"
|
||||
:show-index="false"
|
||||
:is-fold="true"
|
||||
:expand-type="false"
|
||||
primary-key="id">
|
||||
<template slot="action" slot-scope="scope">
|
||||
<Button
|
||||
type="dashed"
|
||||
@click="edit(scope.row)"
|
||||
size="small"
|
||||
style="margin-right:5px"
|
||||
>编辑
|
||||
</Button>
|
||||
<Button
|
||||
v-show="scope.row.level != 1 "
|
||||
type="info"
|
||||
@click="addChildren(scope.row)"
|
||||
size="small"
|
||||
style="margin-right:5px"
|
||||
>添加子分类
|
||||
</Button>
|
||||
<Button
|
||||
type="error"
|
||||
@click="remove(scope.row)"
|
||||
size="small"
|
||||
style="margin-right:5px"
|
||||
>删除
|
||||
</Button>
|
||||
|
||||
</template>
|
||||
</tree-table>
|
||||
|
||||
<Modal :title="modalTitle" v-model="modalVisible" :mask-closable='false' :width="500">
|
||||
<Form ref="formAdd" :model="formAdd" :label-width="100" :rules="formValidate">
|
||||
<div v-if="showParent">
|
||||
<FormItem label="上级分类" prop="parentId">
|
||||
{{ parentTitle }}
|
||||
<Input v-model="formAdd.parentId" clearable style="width:100%;display:none"/>
|
||||
</FormItem>
|
||||
</div>
|
||||
<FormItem label="层级" prop="level" style="display:none">
|
||||
<Input v-model="formAdd.level" clearable style="width:100%"/>
|
||||
</FormItem>
|
||||
<FormItem label="分类名称" prop="labelName">
|
||||
<Input v-model="formAdd.labelName" maxlength="12" clearable style="width:100%"/>
|
||||
</FormItem>
|
||||
<FormItem label="排序值" prop="sortOrder" style="width:345px">
|
||||
<InputNumber v-model="formAdd.sortOrder" min="1"></InputNumber>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="modalVisible=false">取消</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="submit">提交</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as API_Goods from "@/api/goods";
|
||||
|
||||
import TreeTable from "@/views/my-components/tree-table/Table/Table";
|
||||
import uploadPicInput from "@/views/my-components/lili/upload-pic-input";
|
||||
|
||||
export default {
|
||||
name: "lili-components",
|
||||
components: {
|
||||
TreeTable,
|
||||
uploadPicInput
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
submitLoading: false, // 提交loading
|
||||
loading: false, //表格加载的loading
|
||||
expandLevel: 1, // 展开的层级
|
||||
modalType: 0, // 添加或编辑标识
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
modalTitle: "", // 添加或编辑标题
|
||||
showParent: false, // 是否展示上级菜单
|
||||
parentTitle: "", // 父级菜单名称
|
||||
formAdd: { // 添加或编辑表单对象初始化数据
|
||||
parentId: "",
|
||||
labelName: "",
|
||||
sortOrder: 1,
|
||||
level: 0,
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {
|
||||
labelName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入分类名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
title: "分类名称",
|
||||
key: "labelName",
|
||||
align: "left",
|
||||
minWidth: "120px",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "left",
|
||||
headerAlign: "center",
|
||||
width: "280px",
|
||||
type: "template",
|
||||
template: "action",
|
||||
}
|
||||
],
|
||||
tableData: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getAllList();
|
||||
},
|
||||
refresh() {
|
||||
this.loading = true;
|
||||
let that = this;
|
||||
setTimeout(function () {
|
||||
that.loading = false;
|
||||
}, 1000);
|
||||
},
|
||||
//添加子分类
|
||||
addChildren(v) {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加子分类";
|
||||
this.parentTitle = v.labelName;
|
||||
this.formAdd.level = eval(v.level + "+1");
|
||||
this.formAdd.labelName = "";
|
||||
this.showParent = true;
|
||||
delete this.formAdd.id;
|
||||
this.formAdd.parentId = v.id;
|
||||
this.modalVisible = true;
|
||||
},
|
||||
edit(v) {
|
||||
this.modalType = 1;
|
||||
this.modalTitle = "编辑";
|
||||
this.formAdd.id = v.id;
|
||||
this.formAdd.labelName = v.labelName;
|
||||
this.formAdd.level = v.level;
|
||||
this.formAdd.parentId = v.parentId;
|
||||
this.formAdd.sortOrder = v.sortOrder;
|
||||
this.formAdd.image = v.image;
|
||||
this.showParent = false;
|
||||
this.modalVisible = true;
|
||||
},
|
||||
//添加一级分类
|
||||
addParent() {
|
||||
this.modalType = 0;
|
||||
this.formAdd.labelName = "";
|
||||
this.modalTitle = "添加一级分类";
|
||||
this.parentTitle = "顶级分类";
|
||||
this.showParent = true;
|
||||
delete this.formAdd.id;
|
||||
this.formAdd.parentId = 0;
|
||||
this.formAdd.sortOrder = 1
|
||||
this.modalVisible = true;
|
||||
|
||||
},
|
||||
//提交编辑和添加
|
||||
submit() {
|
||||
this.$refs.formAdd.validate(valid => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
if (this.modalType === 0) {
|
||||
// 添加 避免编辑后传入id等数据 记得删除
|
||||
delete this.formAdd.id;
|
||||
API_Goods.addShopGoodsLabel(this.formAdd).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("添加成功");
|
||||
this.getAllList(0);
|
||||
this.modalVisible = false;
|
||||
this.$refs.form.resetFields();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 编辑
|
||||
API_Goods.editShopGoodsLabel(this.formAdd).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("修改成功");
|
||||
this.getAllList(0);
|
||||
this.modalVisible = false;
|
||||
this.$refs.form.resetFields();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
// 记得确认修改此处
|
||||
content: "您确认要删除 " + v.labelName + " ?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
// 删除
|
||||
API_Goods.delCategdelShopGoodsLabel(v.id).then(res => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getAllList();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getAllList() {
|
||||
this.loading = true;
|
||||
API_Goods.getShopGoodsLabelList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
// 仅展开指定级数 默认后台已展开所有
|
||||
let expandLevel = this.expandLevel;
|
||||
res.result.forEach(function (e) {
|
||||
if (expandLevel == 1) {
|
||||
if (e.level == 0) {
|
||||
e.expand = false;
|
||||
}
|
||||
if (e.children && e.children.length > 0) {
|
||||
e.children.forEach(function (c) {
|
||||
if (c.level == 1) {
|
||||
c.expand = false;
|
||||
}
|
||||
if (c.children && c.children.length > 0) {
|
||||
c.children.forEach(function (b) {
|
||||
if (b.level == 2) {
|
||||
b.expand = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (expandLevel == 2) {
|
||||
if (e.level == 0) {
|
||||
e.expand = true;
|
||||
}
|
||||
if (e.children && e.children.length > 0) {
|
||||
e.children.forEach(function (c) {
|
||||
if (c.level == 1) {
|
||||
c.expand = false;
|
||||
}
|
||||
if (c.children && c.children.length > 0) {
|
||||
c.children.forEach(function (b) {
|
||||
if (b.level == 2) {
|
||||
b.expand = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (expandLevel == 3) {
|
||||
if (e.level == 0) {
|
||||
e.expand = true;
|
||||
}
|
||||
if (e.children && e.children.length > 0) {
|
||||
e.children.forEach(function (c) {
|
||||
if (c.level == 1) {
|
||||
c.expand = true;
|
||||
}
|
||||
if (c.children && c.children.length > 0) {
|
||||
c.children.forEach(function (b) {
|
||||
if (b.level == 2) {
|
||||
b.expand = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
this.tableData = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.article {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.href-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.operation {
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
</style>
|
||||
388
seller/src/views/goods/goods-seller/addGoods.scss
Normal file
388
seller/src/views/goods/goods-seller/addGoods.scss
Normal file
@@ -0,0 +1,388 @@
|
||||
/*选择商品品类*/
|
||||
.content-goods-publish {
|
||||
padding: 15px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
background: none repeat 0 0 #fff;
|
||||
|
||||
/*商品品类*/
|
||||
.goods-category {
|
||||
text-align: left;
|
||||
padding: 10px;
|
||||
background: #fafafa;
|
||||
border: 1px solid #e6e6e6;
|
||||
|
||||
ul {
|
||||
padding: 8px 4px 8px 8px;
|
||||
list-style: none;
|
||||
width: 300px;
|
||||
background: none repeat 0 0 #fff;
|
||||
border: 1px solid #e6e6e6;
|
||||
display: inline-block;
|
||||
letter-spacing: normal;
|
||||
margin-right: 15px;
|
||||
vertical-align: top;
|
||||
word-spacing: normal;
|
||||
|
||||
li {
|
||||
line-height: 20px;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
color: #333;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 当前品类被选中的样式 */
|
||||
.activeClass {
|
||||
background-color: #d9edf7;
|
||||
border: 1px solid #bce8f1;
|
||||
color: #3a87ad;
|
||||
}
|
||||
|
||||
/*!*当前选择的商品品类文字*!*/
|
||||
.current-goods-category {
|
||||
text-align: left;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
border: 1px solid #fbeed5;
|
||||
color: #c09853;
|
||||
background-color: #fcf8e3;
|
||||
margin: 10px auto;
|
||||
padding: 8px 35px 8px 14px;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
/*编辑基本信息*/
|
||||
.el-form {
|
||||
padding-bottom: 80px;
|
||||
|
||||
.el-form-item {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
/*平铺*/
|
||||
div.base-info-item > div {
|
||||
margin-left: 5%;
|
||||
}
|
||||
|
||||
div.base-info-item {
|
||||
h4 {
|
||||
margin-bottom: 10px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #f8f8f8;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.form-item-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
padding-left: 80px;
|
||||
|
||||
.layout {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.sku-item-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
.sku-item-content-name {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shop-category-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-view-bottom {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.item-goods-properts-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
word-break: break-all;
|
||||
white-space: normal;
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.item-goods-properts {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/** 审核信息-拒绝原因 */
|
||||
.auth-info {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
width: 30%;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.goods-name-width {
|
||||
width: 50%;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.el-form-item__content {
|
||||
margin-left: 120px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
p.goods-group-manager {
|
||||
padding-left: 7.5%;
|
||||
text-align: left;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/*teatarea*/
|
||||
/deep/ .el-textarea {
|
||||
width: 150%;
|
||||
}
|
||||
|
||||
.seo-text {
|
||||
width: 150%;
|
||||
}
|
||||
}
|
||||
|
||||
/*折叠面板*/
|
||||
.el-collapse-item {
|
||||
/deep/ .el-collapse-item__header {
|
||||
text-align: left;
|
||||
background-color: #f8f8f8;
|
||||
padding: 0 10px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-left: 5%;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
/deep/ .el-form-item__content {
|
||||
margin-left: 120px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
p.goods-group-manager {
|
||||
padding-left: 12%;
|
||||
text-align: left;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/deep/ .el-collapse-item__content {
|
||||
padding: 10px 0;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
/*商品描述*/
|
||||
.goods-intro {
|
||||
line-height: 40;
|
||||
}
|
||||
|
||||
/** 底部步骤 */
|
||||
.footer {
|
||||
width: 88.7%;
|
||||
padding: 10px;
|
||||
background-color: #ffc;
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 10%;
|
||||
text-align: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/*图片上传组件第一张图设置封面*/
|
||||
.goods-images {
|
||||
/deep/ li.el-upload-list__item:first-child {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/deep/ li.el-upload-list__item:first-child:after {
|
||||
content: "封";
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
left: -15px;
|
||||
top: -6px;
|
||||
width: 40px;
|
||||
height: 24px;
|
||||
padding-top: 6px;
|
||||
background: #13ce66;
|
||||
text-align: center;
|
||||
-webkit-transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
-webkit-box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item__label {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.step-view {
|
||||
width: 33%;
|
||||
height: 40px;
|
||||
font-size: 19px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.add-sku-btn {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.sku-item:not(:first-child) {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.preview-picture {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
// text-align: center;
|
||||
border: 1px solid transparent;
|
||||
// justify-self: center;
|
||||
// align-self: center;
|
||||
}
|
||||
|
||||
.preview-picture img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sku-upload-list img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sku-upload-list-cover {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.sku-upload-list:hover .sku-upload-list-cover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sku-upload-list-cover i {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
margin: 0 2px;
|
||||
}
|
||||
.ivu-form-item-content {
|
||||
display: flex;
|
||||
}
|
||||
.required {
|
||||
/deep/ .ivu-form-item-label::before {
|
||||
content: "*";
|
||||
display: inline-block;
|
||||
margin-right: 4px;
|
||||
line-height: 1;
|
||||
font-family: SimSun;
|
||||
font-size: 14px;
|
||||
color: #ed4014;
|
||||
}
|
||||
}
|
||||
.demo-upload-list {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
text-align: center;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
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, 0.6);
|
||||
}
|
||||
.demo-upload-list:hover .demo-upload-list-cover {
|
||||
display: block;
|
||||
}
|
||||
.demo-upload-list-cover i {
|
||||
width: 50%;
|
||||
margin-top: 8px;
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
370
seller/src/views/goods/goods-seller/draftGoods.vue
Normal file
370
seller/src/views/goods/goods-seller/draftGoods.vue
Normal file
@@ -0,0 +1,370 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row v-show="openSearch" @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>
|
||||
<span v-if="drop">
|
||||
<Form-item label="状态" prop="status">
|
||||
<Select
|
||||
v-model="searchForm.marketEnable"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<Option value="DOWN">下架</Option>
|
||||
<Option value="UPPER">上架</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="商品编号" prop="sn">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.sn"
|
||||
placeholder="商品编号"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
</span>
|
||||
<Form-item style="margin-left: -35px" class="br">
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search"
|
||||
>搜索</Button
|
||||
>
|
||||
<Button @click="handleReset">重置</Button>
|
||||
<a class="drop-down" @click="dropDown">
|
||||
{{ dropDownContent }}
|
||||
<Icon :type="dropDownIcon"></Icon>
|
||||
</a>
|
||||
</Form-item>
|
||||
</Form>
|
||||
</Row>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
<Modal
|
||||
:title="modalTitle"
|
||||
v-model="modalVisible"
|
||||
:mask-closable="false"
|
||||
:width="500"
|
||||
>
|
||||
<Form
|
||||
ref="underForm"
|
||||
:model="underForm"
|
||||
:label-width="100"
|
||||
:rules="formValidate"
|
||||
>
|
||||
<FormItem label="下架原因" prop="reason">
|
||||
<Input v-model="underForm.reason" clearable style="width: 100%" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="modalVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="lower(form.id)"
|
||||
>提交</Button
|
||||
>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getDraftGoodsListData, deleteDraftGoods } from "@/api/goods";
|
||||
export default {
|
||||
name: "goods",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
id: "", //要操作的id
|
||||
openSearch: true, // 显示搜索
|
||||
loading: true, // 表单加载状态
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
modalTitle: "", // 添加或编辑标题
|
||||
drop: false,
|
||||
dropDownContent: "展开",
|
||||
dropDownIcon: "ios-arrow-down",
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "create_time", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
underForm: { // 下架表单
|
||||
reason: "",
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
goodsName: "",
|
||||
sn: "",
|
||||
marketEnable: "",
|
||||
price: "",
|
||||
sellerName: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [ // 表头
|
||||
{
|
||||
title: "ID",
|
||||
key: "id",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "商品原图",
|
||||
key: "original",
|
||||
width: 150,
|
||||
align: "center",
|
||||
render: (h, params) => {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: params.row.original,
|
||||
alt: "加载图片失败",
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
width: "80px",
|
||||
height: "60px",
|
||||
margin: "10px 0",
|
||||
"object-fit": "contain",
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "商品价格",
|
||||
key: "price",
|
||||
minWidth: 120
|
||||
},
|
||||
|
||||
{
|
||||
title: "商品库存",
|
||||
key: "quantity",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
key: "createTime",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 200,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "primary",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.editGoods(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"编辑"
|
||||
),
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "error",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.removeDraft(params.row.id);
|
||||
},
|
||||
},
|
||||
},
|
||||
"删除"
|
||||
)
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
let here = this.$route.matched.find((v) => v.name === this.$route.name);
|
||||
this.pageType = here.props.default ? here.props.default.type : "";
|
||||
if (this.pageType === "TEMPLATE") {
|
||||
this.searchForm.saveType = "TEMPLATE";
|
||||
} else {
|
||||
this.searchForm.saveType = "DRAFT";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
editGoods(v) {
|
||||
this.searchForm.saveType === "TEMPLATE" ?
|
||||
this.$router.push({ name: "goods-template-operation-edit", query: { draftId: v.id } }):
|
||||
this.$router.push({ name: "goods-draft-operation-edit", query: { draftId: v.id } });
|
||||
},
|
||||
removeDraft (id) {
|
||||
let showType = this.searchForm.saveType === "TEMPLATE" ? "模版" : "草稿";
|
||||
this.$Modal.confirm({
|
||||
title: "确认审核",
|
||||
content: "您确认要删除id为 " + id + " 的" + showType + "吗?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
deleteDraftGoods(id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
handleReset() {
|
||||
this.$refs.searchForm.resetFields();
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
// 重新加载数据
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
dropDown() {
|
||||
if (this.drop) {
|
||||
this.dropDownContent = "展开";
|
||||
this.dropDownIcon = "ios-arrow-down";
|
||||
} else {
|
||||
this.dropDownContent = "收起";
|
||||
this.dropDownIcon = "ios-arrow-up";
|
||||
}
|
||||
this.drop = !this.drop;
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
// 带多条件搜索参数获取表单数据
|
||||
getDraftGoodsListData(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
watch: {
|
||||
$route(to, from) {
|
||||
this.init();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.search {
|
||||
.operation {
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
.select-clear {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
.drop-down {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
730
seller/src/views/goods/goods-seller/goods.vue
Normal file
730
seller/src/views/goods/goods-seller/goods.vue
Normal file
@@ -0,0 +1,730 @@
|
||||
<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="status">
|
||||
<Select v-model="searchForm.marketEnable" placeholder="请选择" clearable style="width: 200px">
|
||||
<Option value="DOWN">下架</Option>
|
||||
<Option value="UPPER">上架</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="商品编号" prop="sn">
|
||||
<Input type="text" v-model="searchForm.sn" placeholder="商品编号" clearable style="width: 200px" />
|
||||
</Form-item>
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="operation padding-row">
|
||||
<Button @click="addGoods" type="primary">添加商品</Button>
|
||||
<Dropdown @on-click="handleDropdown">
|
||||
<Button type="default">
|
||||
批量操作
|
||||
<Icon type="ios-arrow-down"></Icon>
|
||||
</Button>
|
||||
<DropdownMenu slot="list">
|
||||
<DropdownItem name="uppers">批量上架</DropdownItem>
|
||||
<DropdownItem name="lowers">批量下架</DropdownItem>
|
||||
<DropdownItem name="deleteAll">批量删除</DropdownItem>
|
||||
<DropdownItem name="batchShipTemplate">批量设置运费模板</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</Row>
|
||||
|
||||
<Table :loading="loading" border :columns="columns" :data="data" ref="table" sortable="custom" @on-sort-change="changeSort" @on-selection-change="changeSelect">
|
||||
|
||||
<!-- 商品栏目格式化 -->
|
||||
<template slot="goodsSlot" slot-scope="scope">
|
||||
<div style="margin-top: 5px;height: 90px; display: flex;">
|
||||
<div style="">
|
||||
<img :src="scope.row.original" style="height: 80px;margin-top: 3px;width: 70px">
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 13px;">
|
||||
<div class="div-zoom">
|
||||
<a>{{scope.row.goodsName}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
</Table>
|
||||
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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="500">
|
||||
<Input type="number" v-model="stockAllUpdate" placeholder="全部修改,如不需全部修改,则不需输入" />
|
||||
<Table :columns="updateStockColumns" :data="stockList" border :span-method="handleSpan"></Table>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="updateStockModalVisible = false">取消</Button>
|
||||
<Button type="primary" @click="updateStock">更新</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<!-- 批量设置运费模板 -->
|
||||
<Modal title="批量设置运费模板" v-model="shipTemplateModal" :mask-closable="false" :width="500">
|
||||
<Form ref="shipTemplateForm" :model="shipTemplateForm" :label-width="120">
|
||||
<FormItem class="form-item-view-el" label="运费" prop="freightPayer">
|
||||
<RadioGroup @on-change="logisticsTemplateUndertakerChange" v-model="shipTemplateForm.freightPayer">
|
||||
<Radio label="BUYER">
|
||||
<span>买家承担运费</span>
|
||||
</Radio>
|
||||
<Radio label="STORE">
|
||||
<span>使用物流规则</span>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
|
||||
<FormItem class="form-item-view-el" label="物流模板" prop="templateId" v-if="shipTemplateShow">
|
||||
<Select v-model="shipTemplateForm.templateId" style="width: 200px">
|
||||
<Option v-for="item in logisticsTemplate" :value="item.id" :key="item.id">{{ item.name }}
|
||||
</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="shipTemplateModal = false">取消</Button>
|
||||
<Button type="primary" @click="saveShipTemplate">更新</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getGoodsListDataSeller,
|
||||
getGoodsSkuListDataSeller,
|
||||
updateGoodsSkuStocks,
|
||||
upGoods,
|
||||
lowGoods,
|
||||
deleteGoods,
|
||||
batchShipTemplate,
|
||||
} from "@/api/goods";
|
||||
|
||||
import * as API_Store from "@/api/shops";
|
||||
|
||||
export default {
|
||||
name: "goods",
|
||||
components: {},
|
||||
watch: {
|
||||
$route() {
|
||||
this.getDataList();
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: "", //要操作的id
|
||||
loading: true, // 表单加载状态
|
||||
shipTemplateForm: {
|
||||
freightPayer: "BUYER",
|
||||
},
|
||||
shipTemplateShow: false, //物流模板是否显示
|
||||
shipTemplateModal: false, // 物流模板是否显示
|
||||
logisticsTemplate: [], // 物流列表
|
||||
updateStockModalVisible: false, // 更新库存模态框显隐
|
||||
stockAllUpdate: undefined, // 更新库存数量
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "create_time", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
stockList: [], // 库存列表
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
goodsName: "",
|
||||
sn: "",
|
||||
marketEnable: "",
|
||||
price: "",
|
||||
sellerName: "",
|
||||
},
|
||||
updateStockColumns: [
|
||||
{
|
||||
title: "sku规格",
|
||||
key: "sn",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
return h("div", {}, params.row.simpleSpecs);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "审核状态",
|
||||
key: "isAuth",
|
||||
width: 130,
|
||||
render: (h, params) => {
|
||||
if (params.row.isAuth == "TOBEAUDITED") {
|
||||
return h("div", [
|
||||
h("Badge", {
|
||||
props: {
|
||||
status: "error",
|
||||
text: "待审核",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
} else if (params.row.isAuth == "PASS") {
|
||||
return h("div", [
|
||||
h("Badge", {
|
||||
props: {
|
||||
status: "success",
|
||||
text: "审核通过",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
} else if (params.row.isAuth == "REFUSE") {
|
||||
return h("div", [
|
||||
h("Badge", {
|
||||
props: {
|
||||
status: "error",
|
||||
text: "审核拒绝",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
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;
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
// 表单验证规则
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
{
|
||||
type: "selection",
|
||||
width: 60,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "商品编号",
|
||||
key: "sn",
|
||||
width: 200,
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 200,
|
||||
slot: "goodsSlot",
|
||||
},
|
||||
|
||||
{
|
||||
title: "市场价格",
|
||||
key: "cost",
|
||||
width: 130,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.cost, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "商品价格",
|
||||
key: "price",
|
||||
width: 130,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.price, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "库存",
|
||||
key: "quantity",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
if (params.row.quantity) {
|
||||
return h("div", params.row.quantity);
|
||||
} else {
|
||||
return h("div", 0);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "审核状态",
|
||||
key: "isAuth",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
if (params.row.isAuth == "PASS") {
|
||||
return h("div", [
|
||||
h("Badge", {
|
||||
props: {
|
||||
status: "success",
|
||||
text: "审核通过",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
} else if (params.row.isAuth == "TOBEAUDITED") {
|
||||
return h("div", [
|
||||
h("Badge", {
|
||||
props: {
|
||||
status: "error",
|
||||
text: "待审核",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
} else if (params.row.isAuth == "REFUSE") {
|
||||
return h("div", [
|
||||
h("Badge", {
|
||||
props: {
|
||||
status: "error",
|
||||
text: "审核拒绝",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "上架状态",
|
||||
key: "marketEnable",
|
||||
width: 130,
|
||||
sortable: false,
|
||||
render: (h, params) => {
|
||||
if (params.row.marketEnable == "DOWN") {
|
||||
return h("div", [
|
||||
h("Badge", {
|
||||
props: {
|
||||
status: "error",
|
||||
text: "下架",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
} else if (params.row.marketEnable == "UPPER") {
|
||||
return h("div", [
|
||||
h("Badge", {
|
||||
props: {
|
||||
status: "success",
|
||||
text: "上架",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
} else {
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 200,
|
||||
render: (h, params) => {
|
||||
let enableOrDisable = "";
|
||||
let showEditStock = "";
|
||||
if (params.row.marketEnable == "DOWN") {
|
||||
enableOrDisable = h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
size: "small",
|
||||
type: "success",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.upper(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"上架"
|
||||
);
|
||||
} else {
|
||||
showEditStock = h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "default",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.getStockDetail(params.row.id);
|
||||
},
|
||||
},
|
||||
},
|
||||
"库存"
|
||||
);
|
||||
enableOrDisable = h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "warning",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.lower(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"下架"
|
||||
);
|
||||
}
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.editGoods(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"编辑"
|
||||
),
|
||||
showEditStock,
|
||||
enableOrDisable,
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
addGoods() {
|
||||
this.$router.push({ name: "goods-operation" });
|
||||
},
|
||||
editGoods(v) {
|
||||
this.$router.push({ name: "goods-operation-edit", query: { id: v.id } });
|
||||
},
|
||||
|
||||
//批量操作
|
||||
handleDropdown(v) {
|
||||
//批量上架
|
||||
if (v == "uppers") {
|
||||
this.uppers();
|
||||
}
|
||||
//批量下架
|
||||
if (v == "lowers") {
|
||||
this.lowers();
|
||||
}
|
||||
//批量删除商品
|
||||
if (v == "deleteAll") {
|
||||
this.deleteAll();
|
||||
}
|
||||
//批量设置运费模板
|
||||
if (v == "batchShipTemplate") {
|
||||
this.batchShipTemplate();
|
||||
}
|
||||
},
|
||||
getStockDetail(id) {
|
||||
getGoodsSkuListDataSeller({ goodsId: id, pageSize: 1000 }).then((res) => {
|
||||
if (res.success) {
|
||||
this.updateStockModalVisible = true;
|
||||
this.stockAllUpdate = undefined;
|
||||
this.stockList = res.result.records;
|
||||
}
|
||||
});
|
||||
},
|
||||
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("更新库存成功");
|
||||
}
|
||||
});
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
handleReset() {
|
||||
this.$refs.searchForm.resetFields();
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
// 重新加载数据
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
//保存运费模板信息
|
||||
saveShipTemplate() {
|
||||
if (this.shipTemplateForm.freightPayer == "BUYER") {
|
||||
{
|
||||
this.shipTemplateForm.templateId = 0;
|
||||
}
|
||||
}
|
||||
this.$Modal.confirm({
|
||||
title: "确认设置运费模板",
|
||||
content:
|
||||
"您确认要设置所选的 " + this.selectCount + " 个商品的运费模板?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
let ids = [];
|
||||
this.selectList.forEach(function (e) {
|
||||
ids.push(e.id);
|
||||
});
|
||||
// 批量设置运费模板
|
||||
batchShipTemplate(this.shipTemplateForm).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("运费模板设置成功");
|
||||
this.clearSelectAll();
|
||||
this.getDataList();
|
||||
}
|
||||
this.shipTemplateModal = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
//批量设置运费模板
|
||||
batchShipTemplate() {
|
||||
if (this.selectCount <= 0) {
|
||||
this.$Message.warning("您还未选择要设置运费模板的商品");
|
||||
return;
|
||||
}
|
||||
let data = [];
|
||||
this.selectList.forEach(function (e) {
|
||||
data.push(e.id);
|
||||
});
|
||||
this.shipTemplateForm.goodsId = data;
|
||||
this.shipTemplateModal = true;
|
||||
},
|
||||
//运费承担者变化
|
||||
logisticsTemplateUndertakerChange(v) {
|
||||
//如果是卖家承担运费 需要显示运费模板
|
||||
if (v == "STORE") {
|
||||
API_Store.getShipTemplate().then((res) => {
|
||||
if (res.success) {
|
||||
this.logisticsTemplate = res.result;
|
||||
}
|
||||
});
|
||||
this.shipTemplateShow = true;
|
||||
}
|
||||
if (v == "BUYER") {
|
||||
this.shipTemplateShow = false;
|
||||
}
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
// 带多条件搜索参数获取表单数据
|
||||
getGoodsListDataSeller(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
//下架商品
|
||||
lower(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认下架",
|
||||
content: "您确认要下架 " + v.goodsName + " ?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
let params = {
|
||||
goodsId: v.id,
|
||||
};
|
||||
lowGoods(params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("下架成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
//批量下架
|
||||
lowers() {
|
||||
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.push(e.id);
|
||||
});
|
||||
let params = {
|
||||
goodsId: ids.toString(),
|
||||
};
|
||||
// 批量上架
|
||||
lowGoods(params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("下架成功");
|
||||
this.clearSelectAll();
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
//批量删除商品
|
||||
deleteAll() {
|
||||
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.push(e.id);
|
||||
});
|
||||
let params = {
|
||||
goodsId: ids.toString(),
|
||||
};
|
||||
// 批量删除
|
||||
deleteGoods(params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.clearSelectAll();
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
//批量上架
|
||||
uppers(v) {
|
||||
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.push(e.id);
|
||||
});
|
||||
let params = {
|
||||
goodsId: ids.toString(),
|
||||
};
|
||||
// 批量上架
|
||||
upGoods(params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("上架成功");
|
||||
this.clearSelectAll();
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
upper(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认上架",
|
||||
content: "您确认要上架 " + v.goodsName + " ?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
let params = {
|
||||
goodsId: v.id,
|
||||
};
|
||||
upGoods(params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("上架成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/table-common.scss";
|
||||
/deep/ .ivu-table-wrapper {
|
||||
width: 100% i !important;
|
||||
}
|
||||
</style>
|
||||
1947
seller/src/views/goods/goods-seller/goodsOperation.vue
Normal file
1947
seller/src/views/goods/goods-seller/goodsOperation.vue
Normal file
File diff suppressed because it is too large
Load Diff
347
seller/src/views/goods/goods-seller/goodsStock.vue
Normal file
347
seller/src/views/goods/goods-seller/goodsStock.vue
Normal file
@@ -0,0 +1,347 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row v-show="openSearch" @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>
|
||||
<span v-if="drop">
|
||||
<Form-item label="状态" prop="status">
|
||||
<Select
|
||||
v-model="searchForm.marketEnable"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<Option value="DOWN">下架</Option>
|
||||
<Option value="UPPER">上架</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="商品编号" prop="sn">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.sn"
|
||||
placeholder="商品编号"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
</span>
|
||||
<Form-item style="margin-left: -35px" class="br">
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search"
|
||||
>搜索</Button
|
||||
>
|
||||
<Button @click="handleReset">重置</Button>
|
||||
<a class="drop-down" @click="dropDown">
|
||||
{{ dropDownContent }}
|
||||
<Icon :type="dropDownIcon"></Icon>
|
||||
</a>
|
||||
</Form-item>
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="operation">
|
||||
<Button @click="addGoods" icon="md-refresh">添加商品</Button>
|
||||
<Button @click="getDataList" icon="md-refresh">刷新</Button>
|
||||
<Button type="dashed" @click="openSearch = !openSearch">{{
|
||||
openSearch ? "关闭搜索" : "开启搜索"
|
||||
}}</Button>
|
||||
<Button type="dashed" @click="openTip = !openTip">{{
|
||||
openTip ? "关闭提示" : "开启提示"
|
||||
}}</Button>
|
||||
</Row>
|
||||
<Row v-show="openTip">
|
||||
<Alert show-icon>
|
||||
已选择 <span class="select-count">{{ selectCount }}</span> 项
|
||||
<a class="select-clear" @click="clearSelectAll">清空</a>
|
||||
</Alert>
|
||||
</Row>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
<Modal
|
||||
title="更新库存"
|
||||
v-model="updateStockModalVisible"
|
||||
:mask-closable="false"
|
||||
:width="500"
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
v-model="updateStockParam.quantity"
|
||||
/>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="updateStockModalVisible = false"
|
||||
>取消</Button
|
||||
>
|
||||
<Button type="primary" @click="updateStock">更新</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getGoodsListDataByStockSeller,
|
||||
getGoodsSkuListDataSeller,
|
||||
updateGoodsSkuStocks,
|
||||
upGoods,
|
||||
lowGoods,
|
||||
} from "@/api/goods";
|
||||
export default {
|
||||
name: "goods",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
id: "", //要操作的id
|
||||
openSearch: true, // 显示搜索
|
||||
openTip: true, // 显示提示
|
||||
loading: true, // 表单加载状态
|
||||
updateStockModalVisible: false, // 更新库存模态框
|
||||
drop: false, // 搜索栏更多选项
|
||||
dropDownContent: "展开",
|
||||
dropDownIcon: "ios-arrow-down",
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "create_time", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
updateStockParam: { // 更新库存表单
|
||||
id: 0,
|
||||
quantity: 0,
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
goodsName: "",
|
||||
sn: "",
|
||||
marketEnable: "",
|
||||
price: "",
|
||||
sellerName: "",
|
||||
},
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [ // 表格表头
|
||||
{
|
||||
type: "selection",
|
||||
width: 60,
|
||||
align: "center",
|
||||
},
|
||||
|
||||
{
|
||||
title: "商品缩略图",
|
||||
key: "thumbnail",
|
||||
width: 150,
|
||||
align: "center",
|
||||
render: (h, params) => {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: params.row.thumbnail,
|
||||
alt: "加载图片失败",
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
width: "80px",
|
||||
height: "60px",
|
||||
margin: "10px 0",
|
||||
"object-fit": "contain",
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 120
|
||||
},
|
||||
|
||||
{
|
||||
title: "库存预警数量",
|
||||
key: "stockWarningNum",
|
||||
minWidth: 120
|
||||
},
|
||||
|
||||
{
|
||||
title: "商品库存",
|
||||
key: "quantity",
|
||||
minWidth: 120
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 200,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.getUpdateStock(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"库存"
|
||||
)
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
getUpdateStock(row) {
|
||||
this.updateStockParam = {skuId: row.id, quantity: row.quantity};
|
||||
this.updateStockModalVisible = true;
|
||||
},
|
||||
updateStock() {
|
||||
let updateStockList = [this.updateStockParam];
|
||||
updateGoodsSkuStocks(updateStockList).then(res => {
|
||||
if (res.success) {
|
||||
this.updateStockModalVisible = false;
|
||||
this.$Message.success("更新库存成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
handleReset() {
|
||||
this.$refs.searchForm.resetFields();
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
// 重新加载数据
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
dropDown() {
|
||||
if (this.drop) {
|
||||
this.dropDownContent = "展开";
|
||||
this.dropDownIcon = "ios-arrow-down";
|
||||
} else {
|
||||
this.dropDownContent = "收起";
|
||||
this.dropDownIcon = "ios-arrow-up";
|
||||
}
|
||||
this.drop = !this.drop;
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
// 带多条件搜索参数获取表单数据
|
||||
getGoodsListDataByStockSeller(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.goodsSkuIPage.records.map(i =>{
|
||||
i.stockWarningNum = res.result.stockWarningNum
|
||||
return i;
|
||||
});
|
||||
this.total = res.result.goodsSkuIPage.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.search {
|
||||
.operation {
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
.select-clear {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
.drop-down {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
167
seller/src/views/home/home.scss
Normal file
167
seller/src/views/home/home.scss
Normal file
@@ -0,0 +1,167 @@
|
||||
.card {
|
||||
margin: 10px 10px 20px;
|
||||
padding: 0 20px 20px;
|
||||
background: #fff;
|
||||
border: 1px solid #e7e7e7;
|
||||
|
||||
border-radius: 0.4em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 20px 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
/deep/ .ivu-icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.rate-box {
|
||||
flex: 3.5;
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
> div {
|
||||
padding: 0 20px;
|
||||
|
||||
border-left: 1px solid #ededed;
|
||||
> h5 {
|
||||
|
||||
text-align: center;
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bold {
|
||||
font-size: 18px;
|
||||
}
|
||||
.shop-box {
|
||||
flex: 3;
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
margin-top: 50px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
margin-left: 20px;
|
||||
> .box-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 10px 0;
|
||||
justify-content: space-between;
|
||||
}
|
||||
> .title {
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
.shop {
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.notice-title {
|
||||
margin: 10px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.detail-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.detail-title {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -15px;
|
||||
opacity: 0.3;
|
||||
color: #999;
|
||||
font-size: 21px;
|
||||
text-decoration: initial;
|
||||
transition: 0.35s;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
cursor: pointer;
|
||||
transition: 0.35s;
|
||||
position: relative;
|
||||
font-weight: bold;
|
||||
width: 286px;
|
||||
display: flex;
|
||||
/deep/ span {
|
||||
color: $theme_color;
|
||||
font-size: 18px;
|
||||
}
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
background: #eee;
|
||||
border-radius: 0.4em;
|
||||
margin: 10px;
|
||||
> div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 20px;
|
||||
}
|
||||
}
|
||||
.detail-item:hover {
|
||||
box-shadow: 3px 5px 12px rgba(0, 0, 0, 0.2);
|
||||
transform: translateY(-4px);
|
||||
> .detail-title {
|
||||
opacity: 1;
|
||||
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.shop-logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid #ededed;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.count-item,
|
||||
.todo-item {
|
||||
height: 84px;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
border-radius: 0.4em;
|
||||
flex: 1;
|
||||
font-weight: bold;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
box-shadow: 1px 3px 12px rgba($color: #e7e7e7, $alpha: 0.3);
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 1px 3px 12px rgba($color: #e7e7e7, $alpha: 0.3);
|
||||
}
|
||||
|
||||
.box-left {
|
||||
flex: 8;
|
||||
}
|
||||
.box-right {
|
||||
flex: 2;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.count-item:nth-of-type(1) {
|
||||
background-image: linear-gradient(109.6deg, rgba($color: #ff9a76, $alpha: 0.6) 11.2%, #ff9a76 100.2%);
|
||||
|
||||
box-shadow: 1px 3px 12px rgba($color: #ff9a76, $alpha: 0.3);
|
||||
}
|
||||
.count-item:nth-of-type(2) {
|
||||
background-image: linear-gradient(109.6deg, rgba($color: #4e89ae, $alpha: 0.6) 11.2%, #4e89ae 100.2%);
|
||||
|
||||
box-shadow: 1px 3px 12px rgba($color: #4e89ae, $alpha: 0.3);
|
||||
}
|
||||
.count-item:nth-of-type(3) {
|
||||
background-image: linear-gradient(109.6deg, rgba($color: #679b9b, $alpha: 0.6) 11.2%, #679b9b 100.2%);
|
||||
|
||||
box-shadow: 1px 3px 12px rgba($color: #679b9b, $alpha: 0.3);
|
||||
}
|
||||
.count-item:nth-of-type(4) {
|
||||
background-image: linear-gradient(109.6deg, rgba($color: #637373, $alpha: 0.6) 11.2%, #637373 100.2%);
|
||||
|
||||
box-shadow: 1px 3px 12px rgba($color: #637373, $alpha: 0.3);
|
||||
}
|
||||
259
seller/src/views/home/home.vue
Normal file
259
seller/src/views/home/home.vue
Normal file
@@ -0,0 +1,259 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<Modal v-model="noticeFlage" :title="noticesDetail.title">
|
||||
<div v-if="noticesDetail" v-html="noticesDetail.content">
|
||||
|
||||
</div>
|
||||
</Modal>
|
||||
<div class="box flex">
|
||||
<div class="box-left">
|
||||
<div class="card shop flex">
|
||||
<div>
|
||||
<h4>Hi,<span style="margin-left:5px;">{{userData.nickName}}</span></h4>
|
||||
<img class="shop-logo" :src="userData.storeLogo || require('@/assets/logo1.png')" alt="">
|
||||
</div>
|
||||
<div class="shop-box">
|
||||
<div class="box-item">
|
||||
<div>店铺名称:{{userData.storeName || '暂无'}}</div>
|
||||
|
||||
</div>
|
||||
<div class="box-item">
|
||||
<div>店铺状态:{{userData.storeDisable=='OPEN' ? '开启中' : '关闭'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rate-box">
|
||||
<div>
|
||||
<i-circle :size="120" stroke-color="#fecb89" :trail-width="4" :stroke-width="5" :percent="(userData.serviceScore * 20)" stroke-linecap="square">
|
||||
<div class="demo-Circle-custom">
|
||||
|
||||
<p class="bold">{{userData.serviceScore}}分</p>
|
||||
</div>
|
||||
</i-circle>
|
||||
<h5>服务得分</h5>
|
||||
</div>
|
||||
<div>
|
||||
<i-circle :size="120" stroke-color="#a7c5eb" :trail-width="4" :stroke-width="5" :percent="(userData.deliveryScore * 20)" stroke-linecap="square">
|
||||
<div>
|
||||
|
||||
<p class="bold">{{userData.deliveryScore}}分</p>
|
||||
</div>
|
||||
</i-circle>
|
||||
<h5>交货得分</h5>
|
||||
</div>
|
||||
<div>
|
||||
<i-circle :size="120" stroke-color="#848ccf" :trail-width="4" :stroke-width="5" :percent="(userData.descriptionScore * 20)" stroke-linecap="square">
|
||||
<div>
|
||||
<p class="bold">{{userData.descriptionScore}}分</p>
|
||||
</div>
|
||||
</i-circle>
|
||||
<h5>评价得分</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h4>待办事项</h4>
|
||||
|
||||
<div class="detail-list">
|
||||
<div class="detail-item" @click="navigateTo('order')">
|
||||
<div>
|
||||
<span>{{homeData.unPaidOrder || 0}}</span>
|
||||
<div>待付款</div>
|
||||
</div>
|
||||
<div class="detail-title">
|
||||
交易前
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-item" @click="navigateTo('order')">
|
||||
<div>
|
||||
<span>{{homeData.unDeliveredOrder || 0}}</span>
|
||||
<div>待发货</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{homeData.deliveredOrder || 0}}</span>
|
||||
<div>待收货</div>
|
||||
</div>
|
||||
<div class="detail-title">
|
||||
交易中
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<div @click="navigateTo('returnMoneyOrder')">
|
||||
<span>{{homeData.returnMoney || 0}}</span>
|
||||
<div>退款</div>
|
||||
</div>
|
||||
<div @click="navigateTo('returnGoodsOrder')">
|
||||
<span>{{homeData.returnGoods || 0}}</span>
|
||||
<div>退货</div>
|
||||
</div>
|
||||
<div @click="navigateTo('memberComment')">
|
||||
<span>{{homeData.commentNum || 0}}</span>
|
||||
<div>待评价</div>
|
||||
</div>
|
||||
<div class="detail-title">
|
||||
交易后
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-item" @click="navigateTo('orderComplaint')">
|
||||
<div>
|
||||
<span>{{homeData.deliveredOrder || 0}}</span>
|
||||
<div>待处理</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-title">
|
||||
投诉
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-item" @click="navigateTo('goods')">
|
||||
<div>
|
||||
<span>{{homeData.waitUpper || 0}}</span>
|
||||
<div>待上架</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{homeData.waitAuth || 0}}</span>
|
||||
<div>审核中</div>
|
||||
</div>
|
||||
<div class="detail-title">
|
||||
商品
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-item">
|
||||
<div>
|
||||
<span>{{homeData.seckillNum || 0}}</span>
|
||||
<div>待参加活动</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{homeData.waitPayBill || 0}}</span>
|
||||
<div>待对账</div>
|
||||
</div>
|
||||
<div class="detail-title">
|
||||
其他
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 公告 -->
|
||||
<div class="card box-right">
|
||||
<h4>平台公告</h4>
|
||||
<div>
|
||||
<div class="notice-title" v-for="(item,index) in notices" :key="index">
|
||||
<a @click="clickLinkNotices(item)">{{item.title}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card ">
|
||||
<h4>整体数据</h4>
|
||||
<div class="count-list flex">
|
||||
<div class="count-item" @click="navigateTo('goods')">
|
||||
<div>
|
||||
<Icon class="icon" size="31" type="md-photos" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="counts">{{homeData.goodsNum ||0}}</div>
|
||||
<div>商品数量</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="count-item">
|
||||
<div>
|
||||
<Icon class="icon" size="31" type="ios-card" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="counts">{{homeData.orderPrice ||0}}</div>
|
||||
<div>订单总额</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="count-item" @click="navigateTo('order')">
|
||||
<div>
|
||||
|
||||
<Icon class="icon" size="31" type="md-list" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="counts">{{homeData.orderNum ||0}}</div>
|
||||
<div>订单数量</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="count-item">
|
||||
<div>
|
||||
<Icon class="icon" size="31" type="md-person" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="counts">{{homeData.storeUV ||0}}</div>
|
||||
<div>访客数量</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSellerHomeData, getHomeNotice } from "@/api/index";
|
||||
import { seeArticle } from "@/api/pages";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
export default {
|
||||
name: "home",
|
||||
data() {
|
||||
return {
|
||||
noticeFlage: false, // 控制平台公告显隐
|
||||
|
||||
homeData: {}, // 首页数据
|
||||
userData: "", // 店铺信息
|
||||
notices: "", // 平台公告列表
|
||||
noticesDetail: { // 平台公告详情
|
||||
title: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
navigateTo(name) {
|
||||
this.$router.push({
|
||||
name,
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
let userInfo = JSON.parse(Cookies.get("userInfo"));
|
||||
|
||||
this.userData = userInfo;
|
||||
|
||||
let res = await getHomeNotice();
|
||||
if (res.success) {
|
||||
this.notices = res.result.records;
|
||||
}
|
||||
},
|
||||
|
||||
async clickLinkNotices(val) {
|
||||
let res = await seeArticle(val.id);
|
||||
if (res.success) {
|
||||
this.noticesDetail = res.result;
|
||||
this.noticeFlage = true;
|
||||
}
|
||||
},
|
||||
|
||||
async getHomeData() {
|
||||
let res = await getSellerHomeData();
|
||||
if (res.success) {
|
||||
this.homeData = res.result;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
this.getHomeData();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "./home.scss";
|
||||
</style>
|
||||
155
seller/src/views/lili-components/affix-time.vue
Normal file
155
seller/src/views/lili-components/affix-time.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="breadcrumb">
|
||||
<span @click="clickBreadcrumb(item,index)" :class="{'active':item.selected}" v-for="(item,index) in dateList" :key="index"> {{item.title}}</span>
|
||||
<div class="date-picker">
|
||||
<Select @on-change="changeSelect(selectedWay)" v-model="month" placeholder="年月查询" style="width:200px;margin-left:10px;">
|
||||
<Option v-for="(item,index) in dates" :value="item.year+'-'+item.month" :key="index">{{ item.year+'年'+item.month+'月' }}</Option>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Cookies from "js-cookie";
|
||||
export default {
|
||||
props: ["closeShop"],
|
||||
data() {
|
||||
return {
|
||||
month: "", // 所选月份
|
||||
|
||||
defuaultWay: {
|
||||
title: "最近7天",
|
||||
selected: true,
|
||||
searchType: "LAST_SEVEN",
|
||||
},
|
||||
|
||||
selectedWay: {
|
||||
title: "最近7天",
|
||||
selected: true,
|
||||
searchType: "LAST_SEVEN",
|
||||
},
|
||||
storeId: "", // 店铺id
|
||||
dates: [], // 日期列表
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
storeName: "",
|
||||
storeId: "",
|
||||
},
|
||||
|
||||
dateList: [
|
||||
{
|
||||
title: "今天",
|
||||
selected: false,
|
||||
searchType: "TODAY",
|
||||
},
|
||||
{
|
||||
title: "昨天",
|
||||
selected: false,
|
||||
searchType: "YESTERDAY",
|
||||
},
|
||||
{
|
||||
title: "最近7天",
|
||||
selected: true,
|
||||
searchType: "LAST_SEVEN",
|
||||
},
|
||||
{
|
||||
title: "最近30天",
|
||||
selected: false,
|
||||
searchType: "LAST_THIRTY",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.storeId = JSON.parse(Cookies.get("userInfo")).id;
|
||||
|
||||
|
||||
this.getFiveYears();
|
||||
},
|
||||
methods: {
|
||||
// 获取近5年 年月
|
||||
getFiveYears() {
|
||||
let getYear = new Date().getFullYear();
|
||||
|
||||
let lastFiveYear = getYear - 5;
|
||||
let maxMonth = new Date().getMonth() + 1;
|
||||
let dates = [];
|
||||
// 循环出过去5年
|
||||
for (let year = lastFiveYear; year <= getYear; year++) {
|
||||
for (let month = 1; month <= 12; month++) {
|
||||
if (year == getYear && month > maxMonth) {
|
||||
} else {
|
||||
dates.push({
|
||||
year: year,
|
||||
month: month,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
this.dates = dates.reverse();
|
||||
},
|
||||
|
||||
changeSelect() {
|
||||
if (this.month) {
|
||||
this.dateList.forEach((res) => {
|
||||
res.selected = false;
|
||||
});
|
||||
this.selectedWay.year = this.month.split("-")[0];
|
||||
this.selectedWay.month = this.month.split("-")[1];
|
||||
this.selectedWay.searchType = "";
|
||||
|
||||
this.$emit("selected", this.selectedWay);
|
||||
} else {
|
||||
}
|
||||
},
|
||||
|
||||
clickBreadcrumb(item) {
|
||||
this.dateList.forEach((res) => {
|
||||
res.selected = false;
|
||||
});
|
||||
item.selected = true;
|
||||
item.storeId = this.storeId;
|
||||
this.month = "";
|
||||
|
||||
if (item.searchType == "") {
|
||||
item.searchType = "LAST_SEVEN";
|
||||
}
|
||||
|
||||
this.selectedWay = item;
|
||||
// this.month = "";
|
||||
this.selectedWay.year = new Date().getFullYear();
|
||||
this.selectedWay.month = "";
|
||||
|
||||
this.$emit("selected", this.selectedWay);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.breadcrumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> span {
|
||||
margin-right: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.active {
|
||||
color: $theme_color;
|
||||
position: relative;
|
||||
}
|
||||
.date-picker {
|
||||
}
|
||||
.active:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -10px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
background: $theme_color;
|
||||
}
|
||||
</style>
|
||||
125
seller/src/views/lili-components/multiple-region.vue
Normal file
125
seller/src/views/lili-components/multiple-region.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<Modal :mask-closable="false" :value="switched" v-model="switched" title="选择地址" @on-ok="submit" @on-cancel="cancel">
|
||||
<div class="flex">
|
||||
<Spin size="large" fix v-if="spinShow"></Spin>
|
||||
<Tree ref="tree" class="tree" :data="data" expand-node show-checkbox multiple></Tree>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
<script>
|
||||
import { getChildRegion, getAllCity } from "@/api/index";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
switched: false, // 控制模态框显隐
|
||||
spinShow: false, // 加载loading
|
||||
data: [], // 地区数据
|
||||
selectedWay: [], // 选择的地区
|
||||
callBackData: "", // 打开组件的回显数据
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
this.switched = false;
|
||||
// this.$emit("close",true)
|
||||
},
|
||||
open(val) {
|
||||
if (val) {
|
||||
this.callBackData = val;
|
||||
this.data = JSON.parse(JSON.stringify(this.data));
|
||||
val.areaId.split(",").forEach((ids) => {
|
||||
this.data.forEach((item) => {
|
||||
if (item.id == ids) {
|
||||
item.selected = true;
|
||||
|
||||
}
|
||||
item.children &&
|
||||
item.children.forEach((child) => {
|
||||
if (child.id == ids) {
|
||||
child.checked = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.switched = true;
|
||||
},
|
||||
|
||||
submit() {
|
||||
// 筛选出省市
|
||||
let list = this.$refs.tree.getCheckedAndIndeterminateNodes();
|
||||
let sort = [];
|
||||
list.forEach((item) => {
|
||||
item.selectedList = [];
|
||||
if (item.level == "province") {
|
||||
sort.push({
|
||||
...item,
|
||||
});
|
||||
}
|
||||
sort.forEach((sortItem, sortIndex) => {
|
||||
if (item.level != "province" && sortItem.id == item.parentId) {
|
||||
sortItem.selectedList.push({
|
||||
...item,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.$emit(
|
||||
"selected",
|
||||
list.filter((item) => {
|
||||
return item.level == "province";
|
||||
})
|
||||
);
|
||||
|
||||
this.cancel();
|
||||
},
|
||||
|
||||
init() {
|
||||
getAllCity().then((res) => {
|
||||
if (res.result) {
|
||||
res.result.forEach((item) => {
|
||||
item.children.forEach((child) => {
|
||||
child.title = child.name;
|
||||
});
|
||||
|
||||
let data = {
|
||||
title: item.name,
|
||||
|
||||
...item,
|
||||
};
|
||||
this.data.push(data);
|
||||
this.selectedWay.push({ name: data.title, id: data.id });
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.flex {
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
.tree {
|
||||
flex: 2;
|
||||
}
|
||||
.form {
|
||||
flex: 8;
|
||||
}
|
||||
.button-list {
|
||||
margin-left: 80px;
|
||||
> * {
|
||||
margin: 0 4px;
|
||||
}
|
||||
}
|
||||
/deep/ .ivu-modal-body {
|
||||
height: 400px !important;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
119
seller/src/views/lili-components/region.vue
Normal file
119
seller/src/views/lili-components/region.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div>
|
||||
<Cascader
|
||||
:data="data"
|
||||
:load-data="loadData"
|
||||
change-on-select
|
||||
v-model="dd"
|
||||
@on-visible-change="handleChangeOnSelect"
|
||||
@on-change="change"
|
||||
></Cascader>
|
||||
{{ dd }}
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import * as API_Setup from "@/api/common.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data: [], // 地区数据
|
||||
selected: [], // 已选地区
|
||||
changeOnSelect: false, // 选择时的变化
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
props: ['addressId'],
|
||||
methods: {
|
||||
change(val, selectedData) {
|
||||
/**
|
||||
* @returns [regionId,region]
|
||||
*/
|
||||
this.$emit("selected", [
|
||||
val,
|
||||
selectedData[selectedData.length - 1].__label.split("/"),
|
||||
]);
|
||||
},
|
||||
/**
|
||||
* 动态设置change-on-select的值
|
||||
* 当级联选择器弹窗展开时,设置change-on-select为true,即可以点选菜单选项值发生变化
|
||||
* 当级联选择器弹窗关闭时,设置change-on-select为false,即能够设置初始值
|
||||
*/
|
||||
handleChangeOnSelect(value) {
|
||||
this.changeOnSelect = value;
|
||||
},
|
||||
getArea(val) {
|
||||
},
|
||||
loadData(item, callback) {
|
||||
item.loading = true;
|
||||
API_Setup.getChildRegion(item.value).then((res) => {
|
||||
if (res.result.length <= 0) {
|
||||
item.loading = false;
|
||||
this.selected = item;
|
||||
|
||||
/**
|
||||
* 处理数据并返回
|
||||
*/
|
||||
} else {
|
||||
res.result.forEach((child) => {
|
||||
item.loading = false;
|
||||
|
||||
let data = {
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
loading: false,
|
||||
children: [],
|
||||
};
|
||||
|
||||
if (
|
||||
child.level == "street" ||
|
||||
item.label == "香港特别行政区" ||
|
||||
item.label == "澳门特别行政区"
|
||||
) {
|
||||
item.children.push({
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
});
|
||||
} else {
|
||||
item.children.push(data);
|
||||
}
|
||||
});
|
||||
this.selected = item;
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
init() {
|
||||
API_Setup.getChildRegion(this.id).then((res) => {
|
||||
let way = [];
|
||||
|
||||
res.result.forEach((item) => {
|
||||
let data;
|
||||
// 台湾省做处理
|
||||
if (item.name == "台湾省") {
|
||||
data = {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
};
|
||||
} else {
|
||||
data = {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
loading: false,
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
way.push(data);
|
||||
});
|
||||
|
||||
this.data = way;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
235
seller/src/views/lili-dialog/goods-dialog.vue
Normal file
235
seller/src/views/lili-dialog/goods-dialog.vue
Normal file
@@ -0,0 +1,235 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="wap-content">
|
||||
<div class="query-wrapper">
|
||||
<div class="query-item">
|
||||
<div>搜索范围</div>
|
||||
<Input placeholder="商品名称" @on-clear="goodsData=[]; goodsParams.goodsName=''; getQueryGoodsList()" @on-enter="()=>{goodsData=[]; getQueryGoodsList();}" icon="ios-search" 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>
|
||||
</div>
|
||||
</div>
|
||||
<div style="positon:retavle;">
|
||||
<Scroll class="wap-content-list" :on-reach-bottom="handleReachBottom" :distance-to-edge="[3,3]">
|
||||
|
||||
<div class="wap-content-item" :class="{ active: item.selected }" @click="checkedGoods(item, index)" v-for="(item, index) in goodsData" :key="index">
|
||||
<div>
|
||||
<img :src="item.thumbnail" alt="" />
|
||||
</div>
|
||||
<div class="wap-content-desc">
|
||||
<div class="wap-content-desc-title">{{ item.goodsName }}</div>
|
||||
<div class="wap-sku">{{ item.goodsUnit }}</div>
|
||||
<div class="wap-content-desc-bottom">
|
||||
<div>¥{{ item.price | unitPrice }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Spin size="large" fix v-if="loading"></Spin>
|
||||
|
||||
<div v-if="empty" class="empty">暂无商品信息</div>
|
||||
</Scroll>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as API_Goods from "@/api/goods";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
type: "multiple", //单选或者多选 single multiple
|
||||
|
||||
cateList: [], // 商品分类列表
|
||||
selectedWay: [], //选中商品集合
|
||||
total: "", // 商品总数
|
||||
goodsParams: { // 请求商品列表参数
|
||||
pageNumber: 1,
|
||||
pageSize: 18,
|
||||
order: "desc",
|
||||
goodsName: "",
|
||||
sn: "",
|
||||
categoryPath: "",
|
||||
marketEnable: "UPPER",
|
||||
isAuth: "PASS",
|
||||
},
|
||||
category: [], // 选中的商品分类
|
||||
goodsData: [], // 商品列表
|
||||
empty: false, // 是否空数据
|
||||
loading: false, // 商品加载loading
|
||||
};
|
||||
},
|
||||
props: ["clearFlag"],
|
||||
watch: {
|
||||
category(val) {
|
||||
this.goodsParams.categoryPath = val[2];
|
||||
},
|
||||
selectedWay: {
|
||||
handler() {
|
||||
this.$emit("selected", this.selectedWay);
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
|
||||
"goodsParams.categoryPath": {
|
||||
handler: function () {
|
||||
this.goodsData = [];
|
||||
(this.goodsParams.pageNumber = 0), this.getQueryGoodsList();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
handleReachBottom() {
|
||||
setTimeout(() => {
|
||||
if (
|
||||
this.goodsParams.pageNumber * this.goodsParams.pageSize <=
|
||||
this.total
|
||||
) {
|
||||
this.goodsParams.pageNumber++;
|
||||
this.getQueryGoodsList();
|
||||
}
|
||||
}, 1500);
|
||||
},
|
||||
getQueryGoodsList() {
|
||||
API_Goods.getGoodsSkuData(this.goodsParams).then((res) => {
|
||||
this.initGoods(res);
|
||||
});
|
||||
},
|
||||
|
||||
initGoods(res) {
|
||||
if (res.result.records.length !=0) {
|
||||
res.result.records.forEach((item) => {
|
||||
item.selected = false;
|
||||
item.___type = "goods"; //设置为goods让pc wap知道标识
|
||||
});
|
||||
/**
|
||||
* 解决数据请求中,滚动栏会一直上下跳动
|
||||
*/
|
||||
this.total = res.result.total;
|
||||
this.goodsData.push(...res.result.records);
|
||||
|
||||
} else {
|
||||
this.empty = true;
|
||||
}
|
||||
},
|
||||
|
||||
// 查询商品
|
||||
init() {
|
||||
Promise.all([
|
||||
API_Goods.getGoodsSkuData(this.goodsParams),
|
||||
API_Goods.getGoodsCategoryAll(0),
|
||||
]).then((res) => {
|
||||
// 商品
|
||||
this.initGoods(res[0]);
|
||||
|
||||
// 分类
|
||||
if (res[1].result) {
|
||||
this.deepGroup(res[1].result);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
deepGroup(val) {
|
||||
val.forEach((item) => {
|
||||
let childWay = []; //第二级
|
||||
let grandWay = []; //第三级
|
||||
// 第二层
|
||||
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.cateList.push(way);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击商品
|
||||
*/
|
||||
checkedGoods(val, index) {
|
||||
// 如果单选的话
|
||||
if (this.type != "multiple") {
|
||||
this.goodsData.forEach((item) => {
|
||||
item.selected = false;
|
||||
});
|
||||
this.selectedWay = [];
|
||||
val.selected = true;
|
||||
this.selectedWay.push(val);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (val.selected == false) {
|
||||
val.selected = true;
|
||||
this.selectedWay.push(val);
|
||||
} else {
|
||||
val.selected = false;
|
||||
this.selectedWay.splice(index, 1);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import "./style.scss";
|
||||
.wap-content {
|
||||
width: 100%;
|
||||
}
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding: 8px 0;
|
||||
width: 100%;
|
||||
}
|
||||
.wap-content {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
}
|
||||
.wap-content-list {
|
||||
position: relative;
|
||||
}
|
||||
.wap-content-item {
|
||||
width: 210px;
|
||||
margin: 10px 7px;
|
||||
padding: 6px 0;
|
||||
}
|
||||
// .wap-content-item{
|
||||
|
||||
// }
|
||||
.active {
|
||||
background: url("../../assets/selected.png") no-repeat;
|
||||
background-position: right;
|
||||
background-size: 10%;
|
||||
}
|
||||
</style>
|
||||
106
seller/src/views/lili-dialog/index.vue
Normal file
106
seller/src/views/lili-dialog/index.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<Modal
|
||||
:title="title"
|
||||
:styles="{ top: '120px' }"
|
||||
width="750"
|
||||
@on-cancel="clickClose"
|
||||
@on-ok="clickOK"
|
||||
v-model="flag"
|
||||
:mask-closable="false"
|
||||
scrollable
|
||||
>
|
||||
<goodsDialog
|
||||
@selected="
|
||||
(val) => {
|
||||
goodsData = val;
|
||||
}
|
||||
"
|
||||
ref="goodsDialog"
|
||||
v-if="goodsFlag"
|
||||
/>
|
||||
<linkDialog
|
||||
@selectedLink="
|
||||
(val) => {
|
||||
linkData = val;
|
||||
}
|
||||
"
|
||||
v-else
|
||||
class="linkDialog"
|
||||
/>
|
||||
</Modal>
|
||||
</template>
|
||||
<script>
|
||||
import goodsDialog from "./goods-dialog";
|
||||
import linkDialog from "./link-dialog";
|
||||
export default {
|
||||
components: {
|
||||
goodsDialog,
|
||||
linkDialog,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: "选择", // 模态框标题
|
||||
goodsFlag: false, // 是否商品选择器
|
||||
goodsData: "", //选择的商品
|
||||
linkData: "", //选择的链接
|
||||
flag: false, // 控制模态框显隐
|
||||
};
|
||||
},
|
||||
props: ["types"],
|
||||
watch: {},
|
||||
mounted() {},
|
||||
methods: {
|
||||
// 关闭弹窗
|
||||
clickClose() {
|
||||
this.$emit("closeFlag", false);
|
||||
this.goodsFlag = false;
|
||||
},
|
||||
|
||||
// 单选商品
|
||||
singleGoods(){
|
||||
|
||||
var timer = setInterval(() => {
|
||||
if (this.$refs.goodsDialog) {
|
||||
|
||||
this.$refs.goodsDialog.type = "single";
|
||||
clearInterval(timer);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
|
||||
},
|
||||
clickOK() {
|
||||
if (this.goodsFlag) {
|
||||
this.$emit("selectedGoodsData", this.goodsData);
|
||||
} else {
|
||||
this.$emit("selectedLink", this.linkData);
|
||||
}
|
||||
this.clickClose();
|
||||
// this.clearFlag = false
|
||||
},
|
||||
open(type){
|
||||
this.flag = true;
|
||||
if(type == 'goods'){
|
||||
this.goodsFlag = true;
|
||||
} else {
|
||||
this.goodsFlag = false
|
||||
}
|
||||
|
||||
},
|
||||
close(){
|
||||
this.flag = false;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
/deep/ .ivu-modal {
|
||||
overflow: hidden;
|
||||
height: 650px !important;
|
||||
}
|
||||
/deep/ .ivu-modal-body {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
106
seller/src/views/lili-dialog/link-dialog.vue
Normal file
106
seller/src/views/lili-dialog/link-dialog.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="wap-list">
|
||||
<div
|
||||
class="wap-item"
|
||||
@click="clickTag(item, i)"
|
||||
v-for="(item, i) in wap"
|
||||
:key="i"
|
||||
:class="{ active: selected == i }"
|
||||
>
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="wap-content"></div>
|
||||
|
||||
<!-- 弹出选择商品的modal -->
|
||||
<Modal
|
||||
title="选择"
|
||||
:styles="{ top: '120px' }"
|
||||
width="750"
|
||||
@on-cancel="clickClose"
|
||||
@on-ok="clickClose"
|
||||
v-model="flag"
|
||||
:mask-closable="false"
|
||||
scrollable
|
||||
>
|
||||
<goodsDialog
|
||||
@selected="
|
||||
(val) => {
|
||||
goodsData = val;
|
||||
}
|
||||
"
|
||||
ref="goodsDialog"
|
||||
/>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import wap from "./wap.js";
|
||||
import goodsDialog from "./goods-dialog";
|
||||
export default {
|
||||
components: {
|
||||
goodsDialog,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsData: "", // 商品列表
|
||||
flag: false, // 控制商品模块显隐
|
||||
selected: 0, // 已选模块
|
||||
selectedLink: "", //选中的链接
|
||||
wap,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
selectedLink(val) {
|
||||
|
||||
|
||||
this.$emit("selectedLink", val);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.wap.forEach((item) => {
|
||||
item.selected = false;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
clickClose() {
|
||||
this.flag = false;
|
||||
},
|
||||
|
||||
// 点击链接
|
||||
clickTag(val, i) {
|
||||
this.selected = i;
|
||||
if (!val.openGoods) {
|
||||
this.selectedLink = val;
|
||||
}
|
||||
// 打开选择商品
|
||||
else {
|
||||
this.$refs.goodsDialog.selectedWay = [];
|
||||
this.$refs.goodsDialog.type = "single";
|
||||
this.flag = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import "./style.scss";
|
||||
.wap-content-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.wap-flex {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
/deep/ .ivu-modal {
|
||||
overflow: hidden;
|
||||
height: 650px !important;
|
||||
}
|
||||
/deep/ .ivu-modal-body {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
101
seller/src/views/lili-dialog/style.scss
Normal file
101
seller/src/views/lili-dialog/style.scss
Normal file
@@ -0,0 +1,101 @@
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
.wap-list {
|
||||
flex: 2;
|
||||
text-align: center;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
}
|
||||
> .wap-list,
|
||||
.wap-content {
|
||||
padding: 8px;
|
||||
}
|
||||
.wap-content {
|
||||
flex: 8;
|
||||
}
|
||||
}
|
||||
.wap-sku {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-wrapper {
|
||||
display: flex;
|
||||
margin: 8px 0;
|
||||
> .query-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> * {
|
||||
margin: 0 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
/deep/ .ivu-scroll-container {
|
||||
width: 100% !important;
|
||||
height: 400px !important;
|
||||
}
|
||||
/deep/ .ivu-scroll-content {
|
||||
/* */
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.wap-content-list {
|
||||
overflow-y: auto;
|
||||
}
|
||||
.wap-item {
|
||||
padding: 10px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.wap-item:hover {
|
||||
background: #ededed;
|
||||
}
|
||||
.active{
|
||||
background: #ededed;
|
||||
}
|
||||
.active {
|
||||
border: 1px solid #ededed;
|
||||
}
|
||||
.wap-content-item {
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
height: 80px;
|
||||
padding: 2px;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
margin: 10px;
|
||||
/deep/ img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
text-align: center;
|
||||
}
|
||||
.wap-content-desc {
|
||||
width: 180px;
|
||||
padding: 8px;
|
||||
> .wap-content-desc-title {
|
||||
display: -webkit-box;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
> .wap-content-desc-bottom {
|
||||
font-size: 12px;
|
||||
padding: 4px 0;
|
||||
color: #999;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> div:nth-of-type(1) {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
seller/src/views/lili-dialog/wap.js
Normal file
25
seller/src/views/lili-dialog/wap.js
Normal file
@@ -0,0 +1,25 @@
|
||||
export default [
|
||||
{
|
||||
title:"商品",
|
||||
url:"0",
|
||||
openGoods:true
|
||||
},
|
||||
{
|
||||
title:"分类",
|
||||
url:"1"
|
||||
},
|
||||
{
|
||||
title:"店铺",
|
||||
url:"2"
|
||||
},
|
||||
{
|
||||
title:"活动",
|
||||
url:"3",
|
||||
|
||||
},
|
||||
{
|
||||
title:"其他",
|
||||
url:"4"
|
||||
}
|
||||
|
||||
];
|
||||
258
seller/src/views/login.vue
Normal file
258
seller/src/views/login.vue
Normal file
@@ -0,0 +1,258 @@
|
||||
<template>
|
||||
<div class="login">
|
||||
<Row
|
||||
type="flex"
|
||||
class="row"
|
||||
justify="center"
|
||||
align="middle"
|
||||
@keydown.enter.native="submitLogin"
|
||||
>
|
||||
<Col style="width: 368px">
|
||||
<Header />
|
||||
<Row>
|
||||
<Form
|
||||
ref="usernameLoginForm"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
class="form"
|
||||
>
|
||||
<FormItem prop="username">
|
||||
<Input
|
||||
v-model="form.username"
|
||||
prefix="ios-contact"
|
||||
size="large"
|
||||
clearable
|
||||
placeholder="请输入用户名"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem prop="password">
|
||||
<Input
|
||||
type="password"
|
||||
v-model="form.password"
|
||||
prefix="ios-lock"
|
||||
size="large"
|
||||
password
|
||||
placeholder="请输入密码"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
||||
<Row>
|
||||
<Button
|
||||
class="login-btn"
|
||||
type="primary"
|
||||
size="large"
|
||||
:loading="loading"
|
||||
@click="submitLogin"
|
||||
long
|
||||
>
|
||||
<span v-if="!loading">{{ $t("login") }}</span>
|
||||
<span v-else>{{ $t("logining") }}</span>
|
||||
</Button>
|
||||
</Row>
|
||||
|
||||
</Row>
|
||||
<Footer />
|
||||
</Col>
|
||||
<LangSwitch />
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
login,
|
||||
userMsg,
|
||||
initCaptcha,
|
||||
drawCodeImage,
|
||||
} from "@/api/index";
|
||||
import { validateMobile } from "@/libs/validate";
|
||||
import Cookies from "js-cookie";
|
||||
import Header from "@/views/main-components/header";
|
||||
import Footer from "@/views/main-components/footer";
|
||||
import LangSwitch from "@/views/main-components/lang-switch";
|
||||
import util from "@/libs/util.js";
|
||||
export default {
|
||||
components: {
|
||||
LangSwitch,
|
||||
Header,
|
||||
Footer,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
saveLogin: true, // 保存登录状态
|
||||
loading: false, // 加载状态
|
||||
form: { // 表单数据
|
||||
username: "",
|
||||
password: "",
|
||||
mobile: "",
|
||||
code: "",
|
||||
},
|
||||
rules: { // 验证规则
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: "账号不能为空",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: "密码不能为空",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
imgCode: [
|
||||
{
|
||||
required: true,
|
||||
message: "验证码不能为空",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
mobile: [
|
||||
{
|
||||
required: true,
|
||||
message: "手机号不能为空",
|
||||
trigger: "blur",
|
||||
},
|
||||
{
|
||||
validator: validateMobile,
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
afterLogin(res) {
|
||||
let accessToken = res.result.accessToken;
|
||||
this.setStore("accessToken", accessToken);
|
||||
this.setStore("refreshToken", res.result.refreshToken);
|
||||
|
||||
// 获取用户信息
|
||||
userMsg().then((res) => {
|
||||
if (res.success) {
|
||||
// 避免超过大小限制
|
||||
/* delete res.result.permissions;
|
||||
let roles = [];
|
||||
res.result.roles.forEach((e) => {
|
||||
roles.push(e.name);
|
||||
});
|
||||
this.setStore("roles", roles); */
|
||||
this.setStore("saveLogin", this.saveLogin);
|
||||
if (this.saveLogin) {
|
||||
// 保存7天
|
||||
Cookies.set("userInfo", JSON.stringify(res.result), {
|
||||
expires: 7,
|
||||
});
|
||||
} else {
|
||||
Cookies.set("userInfo", JSON.stringify(res.result));
|
||||
}
|
||||
this.setStore("userInfo", res.result);
|
||||
this.$store.commit("setAvatarPath", res.result.storeLogo);
|
||||
// 加载菜单
|
||||
util.initRouter(this);
|
||||
this.$router.push({
|
||||
name: "home_index",
|
||||
});
|
||||
} else {
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
submitLogin() {
|
||||
// 正常逻辑
|
||||
this.$refs.usernameLoginForm.validate((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
login({
|
||||
username: this.form.username,
|
||||
password: this.md5(this.form.password),
|
||||
}).then((res) => {
|
||||
this.loading = false;
|
||||
if (res && res.success) {
|
||||
this.afterLogin(res);
|
||||
}
|
||||
}).catch(()=>{this.loading = false})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
},
|
||||
mounted() {
|
||||
// this.getCaptchaImg();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.row {
|
||||
padding: 70px 50px;
|
||||
border-radius: .8em;
|
||||
|
||||
}
|
||||
.login {
|
||||
height: 100%;
|
||||
background: url("../assets/background.svg") no-repeat;
|
||||
background-size: 100%;
|
||||
background-position-y: bottom;
|
||||
background-color: #edf0f3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.ivu-tabs-nav-container {
|
||||
line-height: 2;
|
||||
font-size: 17px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
zoom: 1;
|
||||
}
|
||||
/deep/ .ivu-row{
|
||||
display: flex;
|
||||
flex-direction: column !important;
|
||||
}
|
||||
.form {
|
||||
padding-top: 1vh;
|
||||
|
||||
.input-verify {
|
||||
width: 67%;
|
||||
}
|
||||
}
|
||||
|
||||
.forget-pass,
|
||||
.other-way {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.login-btn,
|
||||
.other-login {
|
||||
margin-top: 3vh;
|
||||
}
|
||||
|
||||
.icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.other-icon {
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
|
||||
:hover {
|
||||
color: #2d8cf0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.flex {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
369
seller/src/views/logistics/index.vue
Normal file
369
seller/src/views/logistics/index.vue
Normal file
@@ -0,0 +1,369 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row @keydown.enter.native="handleSearch"> </Row>
|
||||
<Row class="operation">
|
||||
<Button @click="add" type="primary" icon="md-add">添加</Button>
|
||||
<Button @click="getDataList" icon="md-refresh">刷新</Button>
|
||||
<Button type="dashed" @click="openTip = !openTip">{{
|
||||
openTip ? "关闭提示" : "开启提示"
|
||||
}}</Button>
|
||||
</Row>
|
||||
<Row v-show="openTip">
|
||||
<Alert show-icon>
|
||||
已选择 <span class="select-count">{{ selectCount }}</span> 项
|
||||
<a class="select-clear" @click="clearSelectAll">清空</a>
|
||||
</Alert>
|
||||
</Row>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
<Modal
|
||||
:title="modalTitle"
|
||||
v-model="modalVisible"
|
||||
:mask-closable="false"
|
||||
:width="500"
|
||||
>
|
||||
<Form ref="form" :model="form" :label-width="120" :rules="formValidate">
|
||||
<FormItem label="物流公司名称" prop="name">
|
||||
<Input v-model="form.name" clearable style="width: 100%" />
|
||||
</FormItem>
|
||||
<FormItem label="物流公司代码" prop="code">
|
||||
<Input v-model="form.code" clearable style="width: 100%" />
|
||||
</FormItem>
|
||||
<FormItem label="支持电子面单">
|
||||
<i-switch v-model="form.standBy">
|
||||
<span slot="open">开</span>
|
||||
<span slot="close">关</span>
|
||||
</i-switch>
|
||||
</FormItem>
|
||||
<FormItem label="电子面单表单">
|
||||
<Input v-model="form.formItems" clearable style="width: 100%" />
|
||||
</FormItem>
|
||||
<FormItem label="禁用状态" prop="disabled">
|
||||
<i-switch v-model="form.disabled">
|
||||
<span slot="open">开</span>
|
||||
<span slot="close">关</span>
|
||||
</i-switch>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="modalVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
|
||||
>提交</Button
|
||||
>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getLogisticsPage,
|
||||
updateLogistics,
|
||||
getLogisticsDetail,
|
||||
addLogistics,
|
||||
delLogistics,
|
||||
} from "@/api/logistics";
|
||||
export default {
|
||||
name: "bill",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
openTip: true, // 显示提示
|
||||
loading: true, // 表单加载状态
|
||||
modalType: 0, // 添加或编辑标识
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
modalTitle: "", // 添加或编辑标题
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
name: "",
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
name: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入物流公司名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
// 表头
|
||||
{
|
||||
type: "selection",
|
||||
width: 60,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "物流公司名称",
|
||||
key: "name",
|
||||
minWidth: 120
|
||||
},
|
||||
|
||||
{
|
||||
title: "状态",
|
||||
key: "disabled",
|
||||
minWidth: 50,
|
||||
render(h, params) {
|
||||
return h("Badge", {
|
||||
props: {
|
||||
status: params.row.disabled ? "success" : "error",
|
||||
text: params.row.disabled ? "开启" : "关闭",
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 150,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "primary",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"修改"
|
||||
),
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "error",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.remove(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"删除"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
handleReset() {
|
||||
this.$refs.searchForm.resetFields();
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
// 重新加载数据
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
|
||||
getLogisticsPage(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
|
||||
if (this.modalType == 0) {
|
||||
// 添加 避免编辑后传入id等数据 记得删除
|
||||
delete this.form.id;
|
||||
|
||||
this.form.disabled
|
||||
? (this.form.disabled = "OPEN")
|
||||
: (this.form.disabled = "CLOSE");
|
||||
addLogistics(this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 编辑
|
||||
updateLogistics(this.id, this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
add() {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加";
|
||||
this.form = {};
|
||||
this.$refs.form.resetFields();
|
||||
|
||||
this.modalVisible = true;
|
||||
},
|
||||
detail(v) {
|
||||
this.modalType = 1;
|
||||
this.id = v.id;
|
||||
this.modalTitle = "修改";
|
||||
this.modalVisible = true;
|
||||
|
||||
this.form.name = v.name;
|
||||
this.form.code = v.code;
|
||||
this.form.standBy = v.standBy;
|
||||
this.form.formItems = v.formItems;
|
||||
this.form.disabled = v.disabled;
|
||||
this.form.disabled == "OPEN"
|
||||
? (this.form.disabled = true)
|
||||
: (this.form.disabled = false);
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
// 记得确认修改此处
|
||||
content: "您确认要删除 " + v.name + " ?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
// 删除
|
||||
delLogistics(v.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
// @import "@/styles/table-common.scss";
|
||||
.search {
|
||||
.operation {
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
.select-clear {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
|
||||
.drop-down {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
28
seller/src/views/main-components/breadcrumb-nav.vue
Normal file
28
seller/src/views/main-components/breadcrumb-nav.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbItem
|
||||
v-for="item in currentPath"
|
||||
:to="item.path"
|
||||
:key="item.name"
|
||||
>{{ itemTitle(item) }}</BreadcrumbItem>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'breadcrumbNav',
|
||||
props: {
|
||||
currentPath: Array
|
||||
},
|
||||
methods: {
|
||||
itemTitle (item) {
|
||||
if (typeof item.title == 'object') {
|
||||
return this.$t(item.title.i18n);
|
||||
} else {
|
||||
return item.title;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
44
seller/src/views/main-components/footer.vue
Normal file
44
seller/src/views/main-components/footer.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="foot">
|
||||
<Row type="flex" justify="space-around" class="help">
|
||||
<a class="item" href="https://lilishop.com" target="_blank">{{ $t('help') }}</a>
|
||||
<a class="item" href="https://lilishop.com" target="_blank">{{ $t('privacy') }}</a>
|
||||
<a class="item" href="https://lilishop.com" target="_blank">{{ $t('terms') }}</a>
|
||||
</Row>
|
||||
<Row type="flex" justify="center" class="copyright">
|
||||
Copyright © 2020 - Present
|
||||
<a
|
||||
href="http://lili.cn"
|
||||
target="_blank"
|
||||
style="margin:0 5px;"
|
||||
>lili-shop</a> {{ $t('rights') }}
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "footer"
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.foot {
|
||||
position: fixed;
|
||||
bottom: 4vh;
|
||||
width: 368px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: 14px;
|
||||
.help {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1vh;
|
||||
width: 60%;
|
||||
.item {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
:hover {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
80
seller/src/views/main-components/fullscreen.vue
Normal file
80
seller/src/views/main-components/fullscreen.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div @click="handleChange" v-if="showFullScreenBtn" class="full-screen-btn-con">
|
||||
<Tooltip :content="value ? '退出全屏' : '全屏'" placement="bottom">
|
||||
<Icon :type="value ? 'ios-contract' : 'ios-expand'" :size="24"></Icon>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "fullScreen",
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showFullScreenBtn() {
|
||||
return window.navigator.userAgent.indexOf("MSIE") < 0;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleFullscreen() {
|
||||
let main = document.body;
|
||||
if (this.value) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitCancelFullScreen) {
|
||||
document.webkitCancelFullScreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
} else {
|
||||
if (main.requestFullscreen) {
|
||||
main.requestFullscreen();
|
||||
} else if (main.mozRequestFullScreen) {
|
||||
main.mozRequestFullScreen();
|
||||
} else if (main.webkitRequestFullScreen) {
|
||||
main.webkitRequestFullScreen();
|
||||
} else if (main.msRequestFullscreen) {
|
||||
main.msRequestFullscreen();
|
||||
}
|
||||
}
|
||||
},
|
||||
handleChange() {
|
||||
this.handleFullscreen();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
let isFullscreen =
|
||||
document.fullscreenElement ||
|
||||
document.mozFullScreenElement ||
|
||||
document.webkitFullscreenElement ||
|
||||
document.fullScreen ||
|
||||
document.mozFullScreen ||
|
||||
document.webkitIsFullScreen;
|
||||
isFullscreen = !!isFullscreen;
|
||||
document.addEventListener("fullscreenchange", () => {
|
||||
this.$emit("input", !this.value);
|
||||
this.$emit("on-change", !this.value);
|
||||
});
|
||||
document.addEventListener("mozfullscreenchange", () => {
|
||||
this.$emit("input", !this.value);
|
||||
this.$emit("on-change", !this.value);
|
||||
});
|
||||
document.addEventListener("webkitfullscreenchange", () => {
|
||||
this.$emit("input", !this.value);
|
||||
this.$emit("on-change", !this.value);
|
||||
});
|
||||
document.addEventListener("msfullscreenchange", () => {
|
||||
this.$emit("input", !this.value);
|
||||
this.$emit("on-change", !this.value);
|
||||
});
|
||||
this.$emit("input", isFullscreen);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
27
seller/src/views/main-components/header.vue
Normal file
27
seller/src/views/main-components/header.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div>
|
||||
<Row class="header">
|
||||
<img src="../../assets/lili.png" class="logo" width="220px">
|
||||
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "header",
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
|
||||
margin-bottom: 6vh;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center !important;
|
||||
}
|
||||
.logo {
|
||||
transform: scale(3);
|
||||
}
|
||||
</style>
|
||||
32
seller/src/views/main-components/lang-switch.vue
Normal file
32
seller/src/views/main-components/lang-switch.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="lang-icon">
|
||||
<Dropdown @on-click="langChange">
|
||||
<Icon type="md-globe" size="26"/>
|
||||
<DropdownMenu slot="list">
|
||||
<DropdownItem name="zh-CN">简体中文</DropdownItem>
|
||||
<DropdownItem name="en-US">English</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "langSwitch",
|
||||
methods: {
|
||||
langChange(v) {
|
||||
this.$i18n.locale = v;
|
||||
this.$store.commit("switchLang", v);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.lang-icon {
|
||||
position: fixed;
|
||||
top: 2vh;
|
||||
right: 1.5vw;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
34
seller/src/views/main-components/message-tip.vue
Normal file
34
seller/src/views/main-components/message-tip.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div @click="showMessage" class="message-con">
|
||||
<Tooltip :always="value>0" :content="value > 0 ? '有' + value + message : '无未读消息'" placement="bottom">
|
||||
<Badge :count="value" dot>
|
||||
<Icon type="md-notifications" :size="22" />
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import util from "@/libs/util.js";
|
||||
export default {
|
||||
name: "messageTip",
|
||||
props: {
|
||||
value: { // 未读消息数量
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
message:{ // 消息展示内容
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showMessage() {
|
||||
util.openNewPage(this, "message_index");
|
||||
this.$router.push({
|
||||
name: "message_index"
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,57 @@
|
||||
<style lang="scss" scoped>
|
||||
@import "./styles/menu.scss";
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div class="ivu-shrinkable-menu">
|
||||
<!-- 一级菜单 -->
|
||||
<Menu ref="sideMenu" width="110px" theme="dark" :active-name="currNav" @on-select="selectNav">
|
||||
<MenuItem v-for="(item, i) in navList" :key="i" :name="item.name">
|
||||
{{item.title}}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<!-- 二级菜单 -->
|
||||
<Menu
|
||||
ref="childrenMenu"
|
||||
:active-name="$route.name"
|
||||
width="130px"
|
||||
@on-select="changeMenu"
|
||||
>
|
||||
<template v-for="item in menuList">
|
||||
<MenuGroup :title="item.title" :key="item.id" style="padding-left:0;">
|
||||
<MenuItem :name="menu.name" v-for="menu in item.children" :key="menu.name">
|
||||
{{menu.title}}
|
||||
</MenuItem>
|
||||
</MenuGroup>
|
||||
|
||||
</template>
|
||||
</Menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import util from "@/libs/util.js";
|
||||
export default {
|
||||
name: "shrinkableMenu",
|
||||
computed: {
|
||||
menuList() {
|
||||
return this.$store.state.app.menuList;
|
||||
},
|
||||
navList() {
|
||||
return this.$store.state.app.navList;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changeMenu(name) { //二级路由点击
|
||||
this.$router.push({
|
||||
name: name
|
||||
});
|
||||
},
|
||||
selectNav(name) {
|
||||
this.$store.commit("setCurrNav", name);
|
||||
this.setStore("currNav", name);
|
||||
util.initRouter(this);
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,23 @@
|
||||
.ivu-shrinkable-menu{
|
||||
height: calc(100% - 60px);
|
||||
width: 240px;
|
||||
display: flex;
|
||||
}
|
||||
.ivu-menu-vertical .ivu-menu-item-group-title {
|
||||
padding-left: 5px;
|
||||
}
|
||||
.ivu-btn-text:hover {
|
||||
background-color: rgba(255,255,255,.2) !important;
|
||||
}
|
||||
.ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu){
|
||||
background-color: #fff;
|
||||
&:hover{
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
.ivu-menu-vertical{
|
||||
overflow-y: auto;
|
||||
}
|
||||
.ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu){
|
||||
color: #ed3f14;
|
||||
}
|
||||
267
seller/src/views/main-components/tags-page-opened.vue
Normal file
267
seller/src/views/main-components/tags-page-opened.vue
Normal file
@@ -0,0 +1,267 @@
|
||||
<style lang="scss" scoped>
|
||||
@import "../main.scss";
|
||||
</style>
|
||||
|
||||
<template>
|
||||
|
||||
<div
|
||||
ref="scrollCon"
|
||||
@DOMMouseScroll="handlescroll"
|
||||
@mousewheel="handlescroll"
|
||||
class="tags-outer-scroll-con"
|
||||
>
|
||||
<ul v-show="visible" :style="{left: contextMenuLeft + 'px', top: contextMenuTop + 'px'}" class="contextmenu">
|
||||
<li v-for="(item, key) of actionList" @click="handleTagsOption(key)" :key="key">{{item}}</li>
|
||||
</ul>
|
||||
<div ref="scrollBody" class="tags-inner-scroll-body" :style="{left: tagBodyLeft + 'px'}">
|
||||
<transition-group name="taglist-moving-animation">
|
||||
<Tag
|
||||
type="dot"
|
||||
v-for="item in pageTagsList"
|
||||
ref="tagsPageOpened"
|
||||
:key="item.name"
|
||||
:name="item.name"
|
||||
@on-close="closePage"
|
||||
@click.native="linkTo(item)"
|
||||
:closable="item.name=='home_index'?false:true"
|
||||
:color="item.children?(item.children[0].name==currentPageName?'primary':'default'):(item.name==currentPageName?'primary':'default')"
|
||||
@contextmenu.prevent.native="contextMenu(item, $event)"
|
||||
>{{ itemTitle(item) }}</Tag>
|
||||
</transition-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "tagsPageOpened",
|
||||
data() {
|
||||
return {
|
||||
currentPageName: this.$route.name, // 当前路由名称
|
||||
tagBodyLeft: 0, // 标签左偏移量
|
||||
visible: false, // 显示操作按钮
|
||||
contextMenuLeft: 0, // 内容左偏移量
|
||||
contextMenuTop: 0, // 内容上偏移量
|
||||
actionList: {
|
||||
others: '关闭其他',
|
||||
clearAll: '关闭所有'
|
||||
},
|
||||
refsTag: [], // 所有已打开标签
|
||||
tagsCount: 1 // 标签数量
|
||||
};
|
||||
},
|
||||
props: {
|
||||
pageTagsList: Array,
|
||||
beforePush: {
|
||||
type: Function,
|
||||
default: item => {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.$store.state.app.currentTitle;
|
||||
},
|
||||
tagsList() {
|
||||
return this.$store.state.app.storeOpenedList;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
itemTitle(item) {
|
||||
if (typeof item.title == "object") {
|
||||
return this.$t(item.title.i18n);
|
||||
} else {
|
||||
return item.title;
|
||||
}
|
||||
},
|
||||
closePage(event, name) {
|
||||
let storeOpenedList = this.$store.state.app.storeOpenedList;
|
||||
let lastPageObj = storeOpenedList[0];
|
||||
if (this.currentPageName == name) {
|
||||
let len = storeOpenedList.length;
|
||||
for (let i = 1; i < len; i++) {
|
||||
if (storeOpenedList[i].name == name) {
|
||||
if (i < len - 1) {
|
||||
lastPageObj = storeOpenedList[i + 1];
|
||||
} else {
|
||||
lastPageObj = storeOpenedList[i - 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let tagWidth = event.target.parentNode.offsetWidth;
|
||||
this.tagBodyLeft = Math.min(this.tagBodyLeft + tagWidth, 0);
|
||||
}
|
||||
this.$store.commit("removeTag", name);
|
||||
this.$store.commit("closePage", name);
|
||||
storeOpenedList = this.$store.state.app.storeOpenedList;
|
||||
localStorage.storeOpenedList = JSON.stringify(storeOpenedList);
|
||||
if (this.currentPageName == name) {
|
||||
this.linkTo(lastPageObj);
|
||||
}
|
||||
},
|
||||
linkTo(item) {
|
||||
if (this.$route.name == item.name) {
|
||||
return;
|
||||
}
|
||||
let routerObj = {};
|
||||
routerObj.name = item.name;
|
||||
if (item.argu) {
|
||||
routerObj.params = item.argu;
|
||||
}
|
||||
if (item.query) {
|
||||
routerObj.query = item.query;
|
||||
}
|
||||
if (this.beforePush(item)) {
|
||||
this.$router.push(routerObj);
|
||||
}
|
||||
},
|
||||
handlescroll(e) {
|
||||
var type = e.type;
|
||||
let delta = 0;
|
||||
if (type == "DOMMouseScroll" || type == "mousewheel") {
|
||||
delta = e.wheelDelta ? e.wheelDelta : -(e.detail || 0) * 40;
|
||||
}
|
||||
let left = 0;
|
||||
if (delta > 0) {
|
||||
left = Math.min(0, this.tagBodyLeft + delta);
|
||||
} else {
|
||||
if (
|
||||
this.$refs.scrollCon.offsetWidth - 100 <
|
||||
this.$refs.scrollBody.offsetWidth
|
||||
) {
|
||||
if (
|
||||
this.tagBodyLeft <
|
||||
-(
|
||||
this.$refs.scrollBody.offsetWidth -
|
||||
this.$refs.scrollCon.offsetWidth +
|
||||
100
|
||||
)
|
||||
) {
|
||||
left = this.tagBodyLeft;
|
||||
} else {
|
||||
left = Math.max(
|
||||
this.tagBodyLeft + delta,
|
||||
this.$refs.scrollCon.offsetWidth -
|
||||
this.$refs.scrollBody.offsetWidth -
|
||||
100
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.tagBodyLeft = 0;
|
||||
}
|
||||
}
|
||||
this.tagBodyLeft = left;
|
||||
},
|
||||
handleTagsOption(type) {
|
||||
if (type == "clearAll") {
|
||||
this.$store.commit("clearAllTags");
|
||||
this.$router.push({
|
||||
name: "home_index"
|
||||
});
|
||||
} else {
|
||||
this.$store.commit("clearOtherTags", this);
|
||||
}
|
||||
this.tagBodyLeft = 0;
|
||||
},
|
||||
moveToView(tag) {
|
||||
if (tag.offsetLeft < -this.tagBodyLeft) {
|
||||
// 标签在可视区域左侧
|
||||
this.tagBodyLeft = -tag.offsetLeft + 10;
|
||||
} else if (
|
||||
tag.offsetLeft + 10 > -this.tagBodyLeft &&
|
||||
tag.offsetLeft + tag.offsetWidth <
|
||||
-this.tagBodyLeft + this.$refs.scrollCon.offsetWidth - 100
|
||||
) {
|
||||
// 标签在可视区域
|
||||
this.tagBodyLeft = Math.min(
|
||||
0,
|
||||
this.$refs.scrollCon.offsetWidth -
|
||||
100 -
|
||||
tag.offsetWidth -
|
||||
tag.offsetLeft -
|
||||
20
|
||||
);
|
||||
} else {
|
||||
// 标签在可视区域右侧
|
||||
this.tagBodyLeft = -(
|
||||
tag.offsetLeft -
|
||||
(this.$refs.scrollCon.offsetWidth - 100 - tag.offsetWidth) +
|
||||
20
|
||||
);
|
||||
}
|
||||
},
|
||||
contextMenu (item, e) {
|
||||
this.visible = true
|
||||
const offsetLeft = this.$el.getBoundingClientRect().left
|
||||
this.contextMenuLeft = e.clientX - offsetLeft + 10
|
||||
this.contextMenuTop = e.clientY - 64
|
||||
},
|
||||
closeMenu () {
|
||||
this.visible = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.refsTag = this.$refs.tagsPageOpened;
|
||||
setTimeout(() => {
|
||||
this.refsTag.forEach((item, index) => {
|
||||
if (this.$route.name == item.name) {
|
||||
let tag = this.refsTag[index].$el;
|
||||
this.moveToView(tag);
|
||||
}
|
||||
});
|
||||
}, 1); // 这里不设定时器就会有偏移bug
|
||||
this.tagsCount = this.tagsList.length;
|
||||
},
|
||||
watch: {
|
||||
$route(to) {
|
||||
this.currentPageName = to.name;
|
||||
this.$nextTick(() => {
|
||||
this.refsTag.forEach((item, index) => {
|
||||
if (to.name == item.name) {
|
||||
let tag = this.refsTag[index].$el;
|
||||
this.moveToView(tag);
|
||||
}
|
||||
});
|
||||
});
|
||||
this.tagsCount = this.tagsList.length;
|
||||
},
|
||||
visible (value) {
|
||||
if (value) {
|
||||
document.body.addEventListener('click', this.closeMenu)
|
||||
} else {
|
||||
document.body.removeEventListener('click', this.closeMenu)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.contextmenu {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
padding: 5px 0;
|
||||
background: #fff;
|
||||
z-index: 11000;
|
||||
list-style-type: none;
|
||||
border-radius: 4px;
|
||||
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .1);
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 5px 15px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ivu-tag-primary{
|
||||
/deep/ .ivu-tag-dot-inner{
|
||||
background: red !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
331
seller/src/views/main.scss
Normal file
331
seller/src/views/main.scss
Normal file
@@ -0,0 +1,331 @@
|
||||
.lock-screen-back {
|
||||
border-radius: 50%;
|
||||
z-index: -1;
|
||||
box-shadow: 0 0 0 0 #667aa6 inset;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: all 3s;
|
||||
}
|
||||
|
||||
.main {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.unlock-con {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
z-index: 11000;
|
||||
}
|
||||
|
||||
.sidebar-menu-con {
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 21;
|
||||
transition: width 0.3s; // background: rgb(73, 80, 96)
|
||||
background: #fff;
|
||||
box-shadow: rgba(0, 21, 41, 0.35) 2px 0px 6px;
|
||||
}
|
||||
|
||||
.layout-text {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.main-hide-text .layout-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-content-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-header-con {
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
display: block;
|
||||
padding-left: 200px;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
z-index: 20;
|
||||
box-shadow: 0 2px 1px 1px rgba(100, 100, 100, 0.1);
|
||||
transition: padding 0.3s;
|
||||
}
|
||||
|
||||
&-breadcrumb {
|
||||
padding: 8px 15px 0;
|
||||
}
|
||||
|
||||
&-nav {
|
||||
padding: 8px 15px 0;
|
||||
color: #515a6e;
|
||||
font-size: 14px;
|
||||
|
||||
:hover {
|
||||
color: #2d8cf0;
|
||||
transition: color 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&-menu-left {
|
||||
background: #464c5b;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tags-con {
|
||||
height: 40px;
|
||||
z-index: -1;
|
||||
background: #f0f0f0;
|
||||
|
||||
.tags-outer-scroll-con {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding-right: 120px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.tags-inner-scroll-body {
|
||||
position: absolute;
|
||||
padding: 2px 10px;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
transition: left 0.3s ease;
|
||||
}
|
||||
|
||||
.close-all-tag-con {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0;
|
||||
box-sizing: border-box;
|
||||
padding-top: 8px;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
background: white;
|
||||
box-shadow: -3px 0 15px 3px rgba(0, 0, 0, 0.1);
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-header {
|
||||
min-width: 740px;
|
||||
height: 60px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 1px 1px rgba(100, 100, 100, 0.1);
|
||||
position: relative;
|
||||
z-index: 11;
|
||||
|
||||
.navicon-con {
|
||||
margin: 6px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.header-middle-con {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0;
|
||||
// right: 340px;
|
||||
bottom: 0;
|
||||
padding: 10px;
|
||||
// overflow: hidden;
|
||||
}
|
||||
|
||||
.nav4 {
|
||||
width: 300px !important;
|
||||
}
|
||||
|
||||
.header-avator-con {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 300px;
|
||||
|
||||
.options {
|
||||
.ivu-select-dropdown {
|
||||
transform-origin: center top 0px;
|
||||
position: absolute;
|
||||
top: 45px !important;
|
||||
left: -2px;
|
||||
will-change: top, left;
|
||||
}
|
||||
}
|
||||
|
||||
.language {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
padding: 18px 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.switch-theme-con {
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.message-con {
|
||||
display: inline-block;
|
||||
|
||||
padding: 18px 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
i {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.change-skin {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.switch-theme {
|
||||
height: 100%;
|
||||
}
|
||||
.dropList {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
&-menu-con {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
.main-user-name {
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin-right: 5px;
|
||||
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
&-innercon {
|
||||
height: 100%;
|
||||
padding-right: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.full-screen-btn-con {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
padding: 18px 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
i {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.lock-screen-btn-con {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
padding: 18px 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
i {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.single-page-con {
|
||||
min-width: 740px;
|
||||
left: 240px;
|
||||
position: relative;
|
||||
top: 100px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: calc(100% + 52px);
|
||||
|
||||
width: calc(100% - 240px);
|
||||
background-color: #f0f0f0;
|
||||
z-index: 1;
|
||||
transition: left 0.3s;
|
||||
|
||||
.single-page {
|
||||
position: relative;
|
||||
margin: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&-copy {
|
||||
text-align: center;
|
||||
padding: 10px 0 20px;
|
||||
color: #9ea7b4;
|
||||
}
|
||||
}
|
||||
|
||||
.taglist-moving-animation-move {
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.logo-con {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #eee;
|
||||
img {
|
||||
height: 44px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-bar {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.menu-bar::-webkit-scrollbar {
|
||||
// width: 6px;
|
||||
// height: 6px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.menu-bar::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
background: #c3c3c3;
|
||||
}
|
||||
|
||||
.menu-bar::-webkit-scrollbar-track {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.main-nav-menu {
|
||||
bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.loading-position {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
z-index: 100;
|
||||
top: 1px;
|
||||
}
|
||||
390
seller/src/views/member/memberComment.vue
Normal file
390
seller/src/views/member/memberComment.vue
Normal file
@@ -0,0 +1,390 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row @keydown.enter.native="handleSearch">
|
||||
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
|
||||
<Form-item label="会员名称" prop="memberName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.memberName"
|
||||
clearable
|
||||
placeholder="请输入会员名称"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="商品名称" prop="goodsName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.goodsName"
|
||||
clearable
|
||||
placeholder="请输入商品名"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="评价" prop="orderStatus">
|
||||
<Select v-model="searchForm.grade" placeholder="请选择" clearable style="width: 200px">
|
||||
<Option value="GOOD">好评</Option>
|
||||
<Option value="MODERATE">中评</Option>
|
||||
<Option value="WORSE">差评</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="评论日期">
|
||||
<DatePicker
|
||||
v-model="selectDate"
|
||||
type="datetimerange"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
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 class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
<Modal
|
||||
:title="modalTitle"
|
||||
v-model="modalVisible"
|
||||
:mask-closable="false"
|
||||
:width="500"
|
||||
>
|
||||
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
|
||||
<FormItem label="评价内容">
|
||||
<span v-if="!content">暂无评价</span>
|
||||
<span v-else>
|
||||
<div>
|
||||
<Input
|
||||
v-model="content"
|
||||
type="textarea"
|
||||
maxlength="200"
|
||||
disabled
|
||||
:rows="4"
|
||||
clearable
|
||||
style="width:90%"
|
||||
/>
|
||||
</div>
|
||||
</span>
|
||||
</FormItem>
|
||||
<FormItem label="评价图片" style="padding-top: 10px" v-if="detailInfo.haveImage == 1">
|
||||
<upload-pic-thumb
|
||||
v-model="image"
|
||||
:disable="true"
|
||||
:remove="false"
|
||||
></upload-pic-thumb>
|
||||
</FormItem>
|
||||
<FormItem label="回复内容" prop="reply">
|
||||
<Input v-if="replyStatus == false"
|
||||
v-model="form.reply"
|
||||
type="textarea"
|
||||
maxlength="200"
|
||||
:rows="4"
|
||||
clearable
|
||||
style="width:90%"
|
||||
/>
|
||||
<span v-else>
|
||||
<Input
|
||||
v-model="form.reply"
|
||||
type="textarea"
|
||||
maxlength="200"
|
||||
disabled
|
||||
:rows="4"
|
||||
clearable
|
||||
style="width:90%"
|
||||
/>
|
||||
</span>
|
||||
</FormItem>
|
||||
<FormItem label="回复图片" prop="replyImage" style="padding-top: 18px"
|
||||
v-if="detailInfo.haveReplyImage == 1 || replyStatus == false">
|
||||
<upload-pic-thumb v-if="replyStatus == false"
|
||||
v-model="form.replyImage"
|
||||
:limit="5"
|
||||
></upload-pic-thumb>
|
||||
<upload-pic-thumb v-else
|
||||
v-model="form.replyImage"
|
||||
:disable="true"
|
||||
:remove="false"
|
||||
></upload-pic-thumb>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="modalVisible = false">取消</Button>
|
||||
<Button v-if="replyStatus == false" type="primary" :loading="submitLoading" @click="handleSubmit">回复
|
||||
</Button
|
||||
>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Member from "@/api/member";
|
||||
import uploadPicThumb from "@/views/my-components/lili/upload-pic-thumb";
|
||||
|
||||
export default {
|
||||
name: "memberComment",
|
||||
components: {
|
||||
uploadPicThumb
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
detailInfo: [],
|
||||
image: [],//评价图片
|
||||
replyStatus: false,//回复状态
|
||||
modalType: 0, // 添加或编辑标识
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
modalTitle: "", // 添加或编辑标题
|
||||
loading: true, // 表单加载状态
|
||||
content: "",//评价内容
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
startDate: "", // 起始时间
|
||||
endDate: "", // 终止时间
|
||||
},
|
||||
selectDate: null,
|
||||
form: {
|
||||
replyImage: [],
|
||||
reply: ""
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {
|
||||
reply: [
|
||||
{required: true, message: '请输入回复内容', trigger: 'blur'},
|
||||
],
|
||||
},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
columns: [
|
||||
// 表头
|
||||
{
|
||||
title: "会员名称",
|
||||
key: "memberName",
|
||||
minWidth: 150,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 150,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: "评价内容",
|
||||
key: "content",
|
||||
minWidth: 300,
|
||||
tooltip: true
|
||||
|
||||
},
|
||||
{
|
||||
title: "评价",
|
||||
key: "grade",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
if (params.row.grade == "GOOD") {
|
||||
return h("Badge", {props: {status: "success", text: "好评"}})
|
||||
} else if (params.row.grade == "MODERATE") {
|
||||
return h("Badge", {props: {status: "success", text: "中评"}})
|
||||
} else if (params.row.grade == "WORSE") {
|
||||
return h("Badge", {props: {status: "error", text: "差评"}})
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "status",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
if (params.row.status === "OPEN") {
|
||||
return h("Badge", {props: {status: "success", text: "展示"}})
|
||||
} else {
|
||||
return h("Badge", {props: {status: "error", text: "隐藏"}})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "回复状态",
|
||||
key: "replyStatus",
|
||||
width: 110,
|
||||
render: (h, params) => {
|
||||
if (params.row.replyStatus) {
|
||||
return h("Badge", {props: {status: "success", text: "已回复"}})
|
||||
} else {
|
||||
return h("Badge", {props: {status: "error", text: "未回复"}})
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "创建日期",
|
||||
key: "createTime",
|
||||
width: 170,
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"详细"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
API_Member.getMemberReview(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
//回复
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
API_Member.replyMemberReview(this.form.id, this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("回复成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
detail(v) {
|
||||
this.form.replyImage = []
|
||||
this.loading = true;
|
||||
API_Member.getMemberInfoReview(v.id).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
//赋值
|
||||
this.form.id = res.result.id
|
||||
this.content = res.result.content
|
||||
this.form.reply = res.result.reply
|
||||
this.replyStatus = res.result.replyStatus
|
||||
if (res.result.image) {
|
||||
this.image = (res.result.image || "").split(",");
|
||||
}
|
||||
if (res.result.replyImage) {
|
||||
this.form.replyImage = (res.result.replyImage || "").split(",");
|
||||
}
|
||||
this.detailInfo = res.result
|
||||
//弹出框
|
||||
this.modalVisible = true
|
||||
this.modalTitle = "详细"
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
</style>
|
||||
164
seller/src/views/message/message.scss
Normal file
164
seller/src/views/message/message.scss
Normal file
@@ -0,0 +1,164 @@
|
||||
.message-main-con{
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
.message {
|
||||
&-main-con {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
&-mainlist-con {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 10px;
|
||||
width: 300px;
|
||||
bottom: 0;
|
||||
padding: 10px 0;
|
||||
div {
|
||||
padding: 10px;
|
||||
margin: 0 20px;
|
||||
border-bottom: 1px dashed #d2d3d2;
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
.mes-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.message-count-badge-outer {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.message-count-badge {
|
||||
background: #d2d3d2;
|
||||
}
|
||||
.message-count-badge-red {
|
||||
background: #ed3f14;
|
||||
}
|
||||
.mes-type-btn-text {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-content-con {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
left: 300px;
|
||||
background: white;
|
||||
border-radius: 3px;
|
||||
box-shadow: 2px 2px 10px 2px rgba(0, 0, 0, .1);
|
||||
overflow: auto;
|
||||
.message-title-list-con {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.message-content-top-bar {
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
background: white;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-bottom: 1px solid #dededb;
|
||||
.mes-back-btn-con {
|
||||
position: absolute;
|
||||
width: 70px;
|
||||
height: 30px;
|
||||
left: 0;
|
||||
top: 5px;
|
||||
}
|
||||
.mes-title {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 70px;
|
||||
bottom: 0;
|
||||
left: 70px;
|
||||
line-height: 40px;
|
||||
padding: 0 30px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.mes-time-con {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 40px;
|
||||
left: 0;
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #b7b7b5;
|
||||
}
|
||||
.message-content-body {
|
||||
position: absolute;
|
||||
top: 90px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
.message-content {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-fix {
|
||||
position: fixed;
|
||||
right: 2vw;
|
||||
bottom: 3vh;
|
||||
}
|
||||
|
||||
.back-message-list-enter,
|
||||
.back-message-list-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.back-message-list-enter-active,
|
||||
.back-message-list-leave-active {
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.back-message-list-enter-to,
|
||||
.back-message-list-leave {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.view-message-enter,
|
||||
.view-message-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.view-message-enter-active,
|
||||
.view-message-leave-active {
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.view-message-enter-to,
|
||||
.view-message-leave {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.mes-current-type-btn-enter,
|
||||
.mes-current-type-btn-leave-to {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.mes-current-type-btn-enter-active,
|
||||
.mes-current-type-btn-leave-active {
|
||||
transition: all .3s;
|
||||
}
|
||||
|
||||
.mes-current-type-btn-enter-to,
|
||||
.mes-current-type-btn-leave {
|
||||
opacity: 1;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
407
seller/src/views/message/message.vue
Normal file
407
seller/src/views/message/message.vue
Normal file
@@ -0,0 +1,407 @@
|
||||
|
||||
<template>
|
||||
<div class="message-main-con">
|
||||
<div class="message-mainlist-con">
|
||||
<div>
|
||||
<Button @click="setCurrentMesType('unread')" size="large" long type="text">
|
||||
<div class="mes-wrap">
|
||||
<transition name="mes-current-type-btn">
|
||||
<Icon v-show="currentMessageType == 'unread'" type="md-checkmark"></Icon>
|
||||
</transition>
|
||||
<span class="mes-type-btn-text">未读消息</span>
|
||||
<Badge
|
||||
class="message-count-badge-outer"
|
||||
class-name="message-count-badge-red"
|
||||
:count="unReadCount"
|
||||
></Badge>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button @click="setCurrentMesType('read')" size="large" long type="text">
|
||||
<div class="mes-wrap">
|
||||
<transition name="mes-current-type-btn">
|
||||
<Icon v-show="currentMessageType == 'read'" type="md-checkmark"></Icon>
|
||||
</transition>
|
||||
<span class="mes-type-btn-text">已读消息</span>
|
||||
<Badge
|
||||
class="message-count-badge-outer"
|
||||
class-name="message-count-badge"
|
||||
:count="hasReadCount"
|
||||
></Badge>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button @click="setCurrentMesType('recycleBin')" size="large" long type="text">
|
||||
<div class="mes-wrap">
|
||||
<transition name="mes-current-type-btn">
|
||||
<Icon v-show="currentMessageType == 'recycleBin'" type="md-checkmark"></Icon>
|
||||
</transition>
|
||||
<span class="mes-type-btn-text">回收站</span>
|
||||
<Badge
|
||||
class="message-count-badge-outer"
|
||||
class-name="message-count-badge"
|
||||
:count="recycleBinCount"
|
||||
></Badge>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="message-content-con">
|
||||
<transition name="view-message">
|
||||
<div v-if="showMesTitleList" class="message-title-list-con">
|
||||
<Table
|
||||
ref="messageList"
|
||||
:loading="loading"
|
||||
:columns="mesTitleColumns"
|
||||
:data="currentMesList"
|
||||
:no-data-text="noDataText"
|
||||
></Table>
|
||||
<Page
|
||||
:current="params.pageNumber"
|
||||
:total="total"
|
||||
:page-size="params.pageSize"
|
||||
@on-change="changePage"
|
||||
@on-page-size-change="changePageSize"
|
||||
:page-size-opts="[5,10]"
|
||||
size="small"
|
||||
show-total
|
||||
show-elevator
|
||||
show-sizer
|
||||
class="page-fix"
|
||||
></Page>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="back-message-list">
|
||||
<div v-if="!showMesTitleList" class="message-view-content-con">
|
||||
<div class="message-content-top-bar">
|
||||
<span class="mes-back-btn-con">
|
||||
<Button type="text" @click="backMesTitleList">
|
||||
<Icon type="ios-arrow-back"></Icon> 返回
|
||||
</Button>
|
||||
</span>
|
||||
<h3 class="mes-title">{{ mes.title }}</h3>
|
||||
</div>
|
||||
<p class="mes-time-con">
|
||||
<Icon type="android-time"></Icon>
|
||||
{{ mes.time }}
|
||||
</p>
|
||||
<div class="message-content-body">
|
||||
<p class="message-content" v-html="mes.content">{{ mes.content }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cookies from "js-cookie";
|
||||
import * as API_Index from "@/api/index";
|
||||
|
||||
export default {
|
||||
name: "message_index",
|
||||
data() {
|
||||
const markAsReadBtn = (h, params) => {
|
||||
return h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
icon: "md-eye-off",
|
||||
size: "small"
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
// 标记已读
|
||||
let v = params.row;
|
||||
this.loading = true;
|
||||
API_Index.read(v.id).then(res => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.currentMessageType = "unread"
|
||||
this.getAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
"标为已读"
|
||||
);
|
||||
};
|
||||
const deleteMesBtn = (h, params) => {
|
||||
return h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
icon: "md-trash",
|
||||
size: "small",
|
||||
type: "error"
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
// 移除
|
||||
let v = params.row;
|
||||
this.loading = true;
|
||||
API_Index.deleteMessage(v.id).then(res => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.currentMessageType = "read"
|
||||
this.getAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
"删除"
|
||||
);
|
||||
};
|
||||
const restoreBtn = (h, params) => {
|
||||
return h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
icon: "md-redo",
|
||||
size: "small"
|
||||
},
|
||||
style: {
|
||||
margin: "0 5px 0 0"
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
// 还原
|
||||
let v = params.row;
|
||||
API_Index.reductionMessage(v.id).then(res => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.setCurrentMesType("read");
|
||||
this.recycleBinCount -= 1
|
||||
this.hasReadCount +=1
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
"还原"
|
||||
);
|
||||
};
|
||||
const deleteRealBtn = (h, params) => {
|
||||
return h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
icon: "md-trash",
|
||||
size: "small",
|
||||
type: "error"
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
// 彻底删除
|
||||
let v = params.row;
|
||||
this.loading = true;
|
||||
API_Index.clearMessage(v.id).then(res => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.currentMessageType = "recycleBin"
|
||||
this.getAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
"彻底删除"
|
||||
);
|
||||
};
|
||||
return {
|
||||
loading: true, // 列表加载的loading
|
||||
params: { // 请求消息列表参数
|
||||
status: "UN_READY",
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc" // 默认排序方式
|
||||
},
|
||||
total: 0, // 消息列表总数
|
||||
totalUnread: 0, // 未读总数
|
||||
totalRead: 0, // 已读总数
|
||||
totalRemove: 0, // 回收站消息数
|
||||
currentMesList: [], // 当前状态消息
|
||||
unreadMesList: [], // 未读消息
|
||||
hasReadMesList: [], // 已读消息
|
||||
recyclebinList: [], // 回收站消息
|
||||
currentMessageType: "unread", // 当前列表消息状态
|
||||
showMesTitleList: true, // 是否展示消息状态列表
|
||||
unReadCount: 0, // 未读消息数量
|
||||
hasReadCount: 0, // 已读消息数量
|
||||
recycleBinCount: 0, // 回收站消息数量
|
||||
noDataText: "暂无未读消息",
|
||||
mes: { // 展示消息详情
|
||||
title: "",
|
||||
time: "",
|
||||
content: ""
|
||||
},
|
||||
mesTitleColumns: [ // 表格表头
|
||||
|
||||
{
|
||||
title: " ",
|
||||
key: "title",
|
||||
align: "left",
|
||||
ellipsis: true,
|
||||
render: (h, params) => {
|
||||
return h("span", [
|
||||
h(
|
||||
"a",
|
||||
{
|
||||
style: {
|
||||
margin: "0 30px 0 0"
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.showMesTitleList = false;
|
||||
this.mes.title = params.row.title;
|
||||
this.mes.time = params.row.createTime;
|
||||
this.getContent(params.row);
|
||||
}
|
||||
}
|
||||
},
|
||||
params.row.title
|
||||
)
|
||||
]);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: " ",
|
||||
key: "time",
|
||||
align: "center",
|
||||
width: 190,
|
||||
render: (h, params) => {
|
||||
return h("span", [
|
||||
h("Icon", {
|
||||
props: {
|
||||
type: "md-time",
|
||||
size: 16
|
||||
},
|
||||
style: {
|
||||
margin: "0 5px 3px 0"
|
||||
}
|
||||
}),
|
||||
h("span", params.row.createTime)
|
||||
]);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: " ",
|
||||
key: "asread",
|
||||
align: "center",
|
||||
width: 210,
|
||||
render: (h, params) => {
|
||||
if (this.currentMessageType == "unread") {
|
||||
return h("div", [markAsReadBtn(h, params)]);
|
||||
} else if (this.currentMessageType == "read") {
|
||||
return h("div", [deleteMesBtn(h, params)]);
|
||||
} else {
|
||||
return h("div", [
|
||||
restoreBtn(h, params),
|
||||
deleteRealBtn(h, params)
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
changePage(v) {
|
||||
this.params.pageNumber = v;
|
||||
this.refreshMessage();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.params.pageSize = v;
|
||||
this.refreshMessage();
|
||||
},
|
||||
refreshMessage() {
|
||||
let status = "UN_READY";
|
||||
let type = this.currentMessageType;
|
||||
if (type == "unread") {
|
||||
status = "UN_READY";
|
||||
} else if (type == "read") {
|
||||
status = "ALREADY_READY";
|
||||
} else {
|
||||
status = "ALREADY_REMOVE";
|
||||
}
|
||||
this.params.status = status;
|
||||
this.loading = true;
|
||||
API_Index.getMessageSendData(this.params).then(res => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.currentMesList = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
//获取全部数据
|
||||
getAll() {
|
||||
API_Index.getAllMessage(this.params).then(res => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
//未读消息
|
||||
this.unReadCount = res.result.UN_READY.total;
|
||||
this.currentMesList = res.result.UN_READY.records;
|
||||
//已读消息
|
||||
this.hasReadCount = res.result.ALREADY_READY.total;
|
||||
//回收站
|
||||
this.recycleBinCount = res.result.ALREADY_REMOVE.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
deleteMessage(id) {
|
||||
API_Index.deleteMessage(id).then(res => {
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
}
|
||||
});
|
||||
},
|
||||
backMesTitleList() {
|
||||
this.showMesTitleList = true;
|
||||
},
|
||||
setCurrentMesType(type) {
|
||||
if (this.currentMessageType !== type) {
|
||||
this.showMesTitleList = true;
|
||||
}
|
||||
this.currentMessageType = type;
|
||||
if (type == "unread") {
|
||||
this.noDataText = "暂无未读消息";
|
||||
} else if (type == "read") {
|
||||
this.noDataText = "暂无已读消息";
|
||||
} else {
|
||||
this.noDataText = "回收站无消息";
|
||||
}
|
||||
this.params.pageNumber = 1;
|
||||
this.refreshMessage();
|
||||
},
|
||||
getContent(v) {
|
||||
this.mes.content = v.content;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getAll();
|
||||
},
|
||||
watch: {
|
||||
// 监听路由变化通过id获取数据
|
||||
$route(to, from) {
|
||||
if (to.name == "message_index") {
|
||||
this.getAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "./message.scss";
|
||||
</style>
|
||||
|
||||
18
seller/src/views/my-components/lili/circle-loading.vue
Normal file
18
seller/src/views/my-components/lili/circle-loading.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div style="display: inline-block;">
|
||||
<Icon type="ios-loading" size="18" color="#2d8cf0" class="spin-icon-load"></Icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "circleLoading"
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.spin-icon-load {
|
||||
animation: ani-demo-spin 1s linear infinite;
|
||||
}
|
||||
</style>
|
||||
|
||||
247
seller/src/views/my-components/lili/editor.vue
Normal file
247
seller/src/views/my-components/lili/editor.vue
Normal file
@@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="position: relative">
|
||||
<div :id="id" style="text-align: left; min-width: 1080px"></div>
|
||||
<div v-if="showExpand">
|
||||
<div class="e-menu e-code" @click="editHTML">
|
||||
<Icon type="md-code-working" size="22" />
|
||||
</div>
|
||||
<div class="e-menu e-preview" @click="fullscreenModal = true">
|
||||
<Icon type="ios-eye" size="24" />
|
||||
</div>
|
||||
<div class="e-menu e-trash" @click="clear">
|
||||
<Icon type="md-trash" size="18" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
title="编辑html代码"
|
||||
v-model="showHTMLModal"
|
||||
:mask-closable="false"
|
||||
:width="900"
|
||||
:fullscreen="full"
|
||||
>
|
||||
<Input
|
||||
v-if="!full"
|
||||
v-model="dataEdit"
|
||||
:rows="15"
|
||||
type="textarea"
|
||||
style="max-height: 60vh; overflow: auto"
|
||||
/>
|
||||
<Input v-if="full" v-model="dataEdit" :rows="32" type="textarea" />
|
||||
<div slot="footer">
|
||||
<Button @click="full = !full" icon="md-expand">全屏开/关</Button>
|
||||
<Button
|
||||
@click="editHTMLOk"
|
||||
type="primary"
|
||||
icon="md-checkmark-circle-outline"
|
||||
>确定保存</Button
|
||||
>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal title="预览" v-model="fullscreenModal" fullscreen>
|
||||
<div v-html="data">{{ data }}</div>
|
||||
<div slot="footer">
|
||||
<Button @click="fullscreenModal = false">关闭</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uploadFile } from "@/api/index";
|
||||
import E from "wangeditor";
|
||||
import xss from "xss";
|
||||
// 表情包配置 自定义表情可在该js文件中统一修改
|
||||
import { sina } from "@/libs/emoji";
|
||||
export default {
|
||||
name: "editor",
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
default: "editor",
|
||||
},
|
||||
value: String,
|
||||
base64: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showExpand: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
openXss: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editor: null, // 初始化富文本编辑器
|
||||
data: this.value, // 富文本数据
|
||||
dataEdit: "", // 编辑数据
|
||||
showHTMLModal: false, // 显示html
|
||||
full: false, // html全屏开关
|
||||
fullscreenModal: false, // 显示全屏预览
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
initEditor() {
|
||||
let that = this;
|
||||
this.editor = new E(`#${this.id}`);
|
||||
|
||||
// 编辑内容绑定数据
|
||||
this.editor.config.onchange = (html) => {
|
||||
if (this.openXss) {
|
||||
this.data = xss(html);
|
||||
} else {
|
||||
this.data = html;
|
||||
}
|
||||
this.$emit("input", this.data);
|
||||
this.$emit("on-change", this.data);
|
||||
};
|
||||
this.editor.config.showFullScreen = false;
|
||||
// z-index
|
||||
this.editor.config.zIndex = 100;
|
||||
if (this.base64) {
|
||||
// 使用 base64 保存图片
|
||||
this.editor.config.uploadImgShowBase64 = true;
|
||||
} else {
|
||||
// 配置上传图片服务器端地址
|
||||
this.editor.config.uploadImgServer = uploadFile;
|
||||
// lili如要header中传入token鉴权
|
||||
this.editor.config.uploadImgHeaders = {
|
||||
accessToken: that.getStore("accessToken"),
|
||||
};
|
||||
this.editor.config.uploadFileName = "file";
|
||||
this.editor.config.uploadImgHooks = {
|
||||
before: function (xhr, editor, files) {
|
||||
// 图片上传之前触发
|
||||
},
|
||||
success: function (xhr, editor, result) {
|
||||
// 图片上传并返回结果,图片插入成功之后触发
|
||||
},
|
||||
fail: function (xhr, editor, result) {
|
||||
// 图片上传并返回结果,但图片插入错误时触发
|
||||
that.$Message.error("上传图片失败");
|
||||
},
|
||||
error: function (xhr, editor) {
|
||||
// 图片上传出错时触发
|
||||
that.$Message.error("上传图片出错");
|
||||
},
|
||||
timeout: function (xhr, editor) {
|
||||
// 图片上传超时时触发
|
||||
that.$Message.error("上传图片超时");
|
||||
},
|
||||
// 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
|
||||
customInsert: function (insertImg, result, editor) {
|
||||
if (result.success == true) {
|
||||
let url = result.result;
|
||||
insertImg(url);
|
||||
that.$Message.success("上传图片成功");
|
||||
} else {
|
||||
that.$Message.error(result.message);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
this.editor.config.customAlert = function (info) {
|
||||
// info 是需要提示的内容
|
||||
// that.$Message.info(info);
|
||||
};
|
||||
// 字体
|
||||
this.editor.config.fontNames = ["微软雅黑", "宋体", "黑体", "Arial"];
|
||||
// 表情面板可以有多个 tab ,因此要配置成一个数组。数组每个元素代表一个 tab 的配置
|
||||
this.editor.config.emotions = [
|
||||
{
|
||||
// tab 的标题
|
||||
title: "新浪",
|
||||
// type -> 'emoji' / 'image'
|
||||
type: "image",
|
||||
// content -> 数组
|
||||
content: sina,
|
||||
},
|
||||
];
|
||||
if (this.value) {
|
||||
if (this.openXss) {
|
||||
this.editor.txt.html(xss(this.value));
|
||||
} else {
|
||||
this.editor.txt.html(this.value);
|
||||
}
|
||||
}
|
||||
this.editor.create();
|
||||
},
|
||||
editHTML() {
|
||||
this.dataEdit = this.data;
|
||||
this.showHTMLModal = true;
|
||||
},
|
||||
editHTMLOk() {
|
||||
this.editor.txt.html(this.dataEdit);
|
||||
this.$emit("input", this.data);
|
||||
this.$emit("on-change", this.data);
|
||||
this.showHTMLModal = false;
|
||||
},
|
||||
clear() {
|
||||
this.$Modal.confirm({
|
||||
title: "确认清空",
|
||||
content: "确认要清空编辑器内容?清空后不能撤回",
|
||||
onOk: () => {
|
||||
this.data = "";
|
||||
this.editor.txt.html(this.data);
|
||||
this.$emit("input", this.data);
|
||||
this.$emit("on-change", this.data);
|
||||
},
|
||||
});
|
||||
},
|
||||
setData(value) {
|
||||
if (!this.editor) {
|
||||
this.initEditor();
|
||||
}
|
||||
if (value && value != this.data) {
|
||||
this.data = value;
|
||||
this.editor.txt.html(this.data);
|
||||
this.$emit("input", this.data);
|
||||
this.$emit("on-change", this.data);
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler: function (val) {
|
||||
|
||||
this.setData(val);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.initEditor();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.e-menu {
|
||||
z-index: 101;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
color: #999;
|
||||
:hover {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
.e-code {
|
||||
top: 6px;
|
||||
left: 976px;
|
||||
}
|
||||
.e-preview {
|
||||
top: 6px;
|
||||
left: 1014px;
|
||||
}
|
||||
.e-trash {
|
||||
top: 4px;
|
||||
left: 1047px;
|
||||
}
|
||||
</style>
|
||||
|
||||
166
seller/src/views/my-components/lili/set-password.vue
Normal file
166
seller/src/views/my-components/lili/set-password.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<div class="set-password">
|
||||
<Poptip transfer trigger="focus" placement="right" width="250">
|
||||
<Input
|
||||
type="password"
|
||||
password
|
||||
style="width:350px;"
|
||||
:maxlength="maxlength"
|
||||
v-model="currentValue"
|
||||
@on-change="handleChange"
|
||||
:size="size"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
/>
|
||||
<div :class="tipStyle" slot="content">
|
||||
<div class="words">强度 : {{strength}}</div>
|
||||
<Progress
|
||||
:percent="strengthValue"
|
||||
:status="progressStatus"
|
||||
hide-info
|
||||
style="margin: 13px 0;"
|
||||
/>
|
||||
<br />请至少输入 6 个字符。请不要使
|
||||
<br />用容易被猜到的密码。
|
||||
</div>
|
||||
</Poptip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "setPassword",
|
||||
props: {
|
||||
value: String,
|
||||
size: String,
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "请输入密码,长度为6-20个字符"
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: 20
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value, // 当前密码
|
||||
tipStyle: "password-tip-none", // 提示样式
|
||||
strengthValue: 0, // 密码强度
|
||||
progressStatus: "normal", // 进度条状态
|
||||
strength: "无", // 密码长度
|
||||
grade: 0 // 强度等级
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
checkStrengthValue(v) {
|
||||
// 评级制判断密码强度 最高5
|
||||
let grade = 0;
|
||||
if (/\d/.test(v)) {
|
||||
grade++; //数字
|
||||
}
|
||||
if (/[a-z]/.test(v)) {
|
||||
grade++; //小写
|
||||
}
|
||||
if (/[A-Z]/.test(v)) {
|
||||
grade++; //大写
|
||||
}
|
||||
if (/\W/.test(v)) {
|
||||
grade++; //特殊字符
|
||||
}
|
||||
if (v.length >= 10) {
|
||||
grade++;
|
||||
}
|
||||
this.grade = grade;
|
||||
return grade;
|
||||
},
|
||||
strengthChange() {
|
||||
if (!this.currentValue) {
|
||||
this.tipStyle = "password-tip-none";
|
||||
this.strength = "无";
|
||||
this.strengthValue = 0;
|
||||
return;
|
||||
}
|
||||
let grade = this.checkStrengthValue(this.currentValue);
|
||||
if (grade <= 1) {
|
||||
this.progressStatus = "wrong";
|
||||
this.tipStyle = "password-tip-weak";
|
||||
this.strength = "弱";
|
||||
this.strengthValue = 33;
|
||||
} else if (grade >= 2 && grade <= 4) {
|
||||
this.progressStatus = "normal";
|
||||
this.tipStyle = "password-tip-middle";
|
||||
this.strength = "中";
|
||||
this.strengthValue = 66;
|
||||
} else {
|
||||
this.progressStatus = "success";
|
||||
this.tipStyle = "password-tip-strong";
|
||||
this.strength = "强";
|
||||
this.strengthValue = 100;
|
||||
}
|
||||
},
|
||||
handleChange(v) {
|
||||
this.strengthChange();
|
||||
this.$emit("input", this.currentValue);
|
||||
this.$emit("on-change", this.currentValue, this.grade, this.strength);
|
||||
},
|
||||
setCurrentValue(value) {
|
||||
if (value === this.currentValue) {
|
||||
return;
|
||||
}
|
||||
this.currentValue = value;
|
||||
this.strengthChange();
|
||||
this.$emit("on-change", this.currentValue, this.grade, this.strength);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.setCurrentValue(val);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.set-password .ivu-poptip,
|
||||
.set-password .ivu-poptip-rel {
|
||||
display: block;
|
||||
}
|
||||
.password-tip-none {
|
||||
padding: 1vh 0;
|
||||
}
|
||||
|
||||
.password-tip-weak {
|
||||
padding: 1vh 0;
|
||||
|
||||
.words {
|
||||
color: #ed3f14;
|
||||
}
|
||||
}
|
||||
|
||||
.password-tip-middle {
|
||||
padding: 1vh 0;
|
||||
|
||||
.words {
|
||||
color: #2d8cf0;
|
||||
}
|
||||
}
|
||||
|
||||
.password-tip-strong {
|
||||
padding: 1vh 0;
|
||||
|
||||
.words {
|
||||
color: #52c41a;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
172
seller/src/views/my-components/lili/upload-pic-input.vue
Normal file
172
seller/src/views/my-components/lili/upload-pic-input.vue
Normal file
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="display:flex;">
|
||||
<Input
|
||||
v-model="currentValue"
|
||||
@on-change="handleChange"
|
||||
v-show="showInput"
|
||||
:placeholder="placeholder"
|
||||
:size="size"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:maxlength="maxlength"
|
||||
>
|
||||
<Button slot="append" icon="md-eye"></Button>
|
||||
</Input>
|
||||
<Poptip transfer trigger="hover" title="图片预览" placement="right" width="350">
|
||||
<Icon type="md-eye" class="see-icon" />
|
||||
<div slot="content">
|
||||
<img :src="currentValue" alt="该资源不存在" style="width: 100%;margin: 0 auto;display: block;" />
|
||||
<a @click="viewImage=true" style="margin-top:5px;text-align:right;display:block">查看大图</a>
|
||||
</div>
|
||||
</Poptip>
|
||||
<Upload
|
||||
:action="uploadFileUrl"
|
||||
:headers="accessToken"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:format="['jpg','jpeg','png','gif','bmp']"
|
||||
accept=".jpg, .jpeg, .png, .gif, .bmp"
|
||||
:max-size="maxSize*1024"
|
||||
:on-format-error="handleFormatError"
|
||||
:on-exceeded-size="handleMaxSize"
|
||||
:before-upload="beforeUpload"
|
||||
:show-upload-list="false"
|
||||
ref="up"
|
||||
class="upload"
|
||||
>
|
||||
<Button :loading="loading" :size="size" :disabled="disabled" :icon="icon">上传图片</Button>
|
||||
</Upload>
|
||||
</div>
|
||||
|
||||
<Modal title="图片预览" v-model="viewImage" :styles="{top: '30px'}" draggable>
|
||||
<img :src="currentValue" alt="该资源不存在" style="width: 100%;margin: 0 auto;display: block;" />
|
||||
<div slot="footer">
|
||||
<Button @click="viewImage=false">关闭</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uploadFile } from "@/api/index";
|
||||
export default {
|
||||
name: "uploadPicInput",
|
||||
props: {
|
||||
value: String,
|
||||
size: String,
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "图片链接"
|
||||
},
|
||||
showInput: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
maxlength: Number,
|
||||
icon: {
|
||||
type: String,
|
||||
default: "ios-cloud-upload-outline"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
accessToken: {}, // 验证token
|
||||
currentValue: this.value, // 当前值
|
||||
loading: false, // 加载状态
|
||||
viewImage: false, // 是否预览图片
|
||||
uploadFileUrl: uploadFile // 上传列表
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.accessToken = {
|
||||
accessToken: this.getStore("accessToken")
|
||||
};
|
||||
},
|
||||
handleFormatError(file) {
|
||||
this.loading = false;
|
||||
this.$Notice.warning({
|
||||
title: "不支持的文件格式",
|
||||
desc:
|
||||
"所选文件‘ " +
|
||||
file.name +
|
||||
" ’格式不正确, 请选择 .jpg .jpeg .png .gif .bmp格式文件"
|
||||
});
|
||||
},
|
||||
handleMaxSize(file) {
|
||||
this.loading = false;
|
||||
this.$Notice.warning({
|
||||
title: "文件大小过大",
|
||||
desc: "所选文件‘ " + file.name + " ’大小过大, 不得超过 " + this.maxSize + "M."
|
||||
});
|
||||
},
|
||||
beforeUpload() {
|
||||
this.loading = true;
|
||||
return true;
|
||||
},
|
||||
handleSuccess(res, file) {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.currentValue = res.result;
|
||||
this.$emit("input", this.currentValue);
|
||||
this.$emit("on-change", this.currentValue);
|
||||
} else {
|
||||
this.$Message.error(res.message);
|
||||
}
|
||||
},
|
||||
handleError(error, file, fileList) {
|
||||
this.loading = false;
|
||||
this.$Message.error(error.toString());
|
||||
},
|
||||
handleChange(v) {
|
||||
this.$emit("input", this.currentValue);
|
||||
this.$emit("on-change", this.currentValue);
|
||||
this.$attrs.rollback && this.$attrs.rollback()
|
||||
},
|
||||
setCurrentValue(value) {
|
||||
if (value === this.currentValue) {
|
||||
return;
|
||||
}
|
||||
this.currentValue = value;
|
||||
this.$emit("on-change", this.currentValue);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.setCurrentValue(val);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.see-icon {
|
||||
font-size: 16px;
|
||||
margin-left: -32px;
|
||||
margin-top: 3px;
|
||||
padding: 7px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.upload {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
296
seller/src/views/my-components/lili/upload-pic-thumb.vue
Normal file
296
seller/src/views/my-components/lili/upload-pic-thumb.vue
Normal file
@@ -0,0 +1,296 @@
|
||||
<template>
|
||||
<div>
|
||||
<vuedraggable
|
||||
:list="uploadList"
|
||||
:disabled="!draggable||!multiple"
|
||||
:animation="200"
|
||||
class="list-group"
|
||||
ghost-class="thumb-ghost"
|
||||
@end="onEnd"
|
||||
>
|
||||
<div class="upload-list" v-for="(item, index) in uploadList" :key="index">
|
||||
<div v-if="item.status == 'finished'">
|
||||
<img :src="item.url" />
|
||||
<div class="upload-list-cover">
|
||||
<Icon type="ios-eye-outline" @click="handleView(item.url)"></Icon>
|
||||
<Icon v-if="remove" type="ios-trash-outline" @click="handleRemove(item)"></Icon>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>
|
||||
</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="maxSize*1024"
|
||||
:on-format-error="handleFormatError"
|
||||
:on-exceeded-size="handleMaxSize"
|
||||
:before-upload="handleBeforeUpload"
|
||||
type="drag"
|
||||
:action="uploadFileUrl"
|
||||
:headers="accessToken"
|
||||
style="display: inline-block;width:58px;"
|
||||
>
|
||||
<div style="width: 58px;height:58px;line-height: 58px;">
|
||||
<Icon type="md-camera" size="20"></Icon>
|
||||
</div>
|
||||
</Upload>
|
||||
|
||||
<Modal title="图片预览" v-model="viewImage" :styles="{top: '30px'}" draggable>
|
||||
<img :src="imgUrl" alt="无效的图片链接" style="width: 100%;margin: 0 auto;display: block;" />
|
||||
<div slot="footer">
|
||||
<Button @click="viewImage=false">关闭</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uploadFile } from "@/api/index";
|
||||
import vuedraggable from "vuedraggable";
|
||||
export default {
|
||||
name: "uploadPicThumb",
|
||||
components: {
|
||||
vuedraggable
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
},
|
||||
draggable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
disable:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
remove:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 10
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
accessToken: {}, // 验证token
|
||||
uploadFileUrl: uploadFile, // 上传文件
|
||||
uploadList: [], // 上传文件列表
|
||||
viewImage: false, // 是否预览图片
|
||||
imgUrl: "" // 图片地址
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onEnd() {
|
||||
this.returnValue();
|
||||
},
|
||||
init() {
|
||||
this.setData(this.value, true);
|
||||
this.accessToken = {
|
||||
accessToken: this.getStore("accessToken")
|
||||
};
|
||||
},
|
||||
handleView(imgUrl) {
|
||||
this.imgUrl = imgUrl;
|
||||
this.viewImage = true;
|
||||
},
|
||||
handleRemove(file) {
|
||||
const uploadList = this.uploadList;
|
||||
this.uploadList.splice(uploadList.indexOf(file), 1);
|
||||
this.returnValue();
|
||||
},
|
||||
handleSuccess(res, file) {
|
||||
if (res.success) {
|
||||
file.url = res.result;
|
||||
// 单张图片处理
|
||||
if (!this.multiple && this.uploadList.length > 0) {
|
||||
// 删除第一张
|
||||
this.uploadList.splice(0, 1);
|
||||
}
|
||||
this.uploadList.push(file);
|
||||
// 返回组件值
|
||||
this.returnValue();
|
||||
} else {
|
||||
this.$Message.error(res.message);
|
||||
}
|
||||
},
|
||||
handleError(error, file, fileList) {
|
||||
this.$Message.error(error.toString());
|
||||
},
|
||||
handleFormatError(file) {
|
||||
this.$Notice.warning({
|
||||
title: "不支持的文件格式",
|
||||
desc:
|
||||
"所选文件‘ " +
|
||||
file.name +
|
||||
" ’格式不正确, 请选择 .jpg .jpeg .png .gif图片格式文件"
|
||||
});
|
||||
},
|
||||
handleMaxSize(file) {
|
||||
this.$Notice.warning({
|
||||
title: "文件大小过大",
|
||||
desc:
|
||||
"所选文件‘ " +
|
||||
file.name +
|
||||
" ’大小过大, 不得超过 " +
|
||||
this.maxSize +
|
||||
"M."
|
||||
});
|
||||
},
|
||||
handleBeforeUpload() {
|
||||
if (this.multiple && this.uploadList.length >= this.limit) {
|
||||
this.$Message.warning("最多只能上传" + this.limit + "张图片");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
returnValue() {
|
||||
if (!this.uploadList || this.uploadList.length < 1) {
|
||||
if (!this.multiple) {
|
||||
this.$emit("input", "");
|
||||
this.$emit("on-change", "");
|
||||
} else {
|
||||
this.$emit("input", []);
|
||||
this.$emit("on-change", []);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!this.multiple) {
|
||||
// 单张
|
||||
let v = this.uploadList[0].url;
|
||||
this.$emit("input", v);
|
||||
this.$emit("on-change", v);
|
||||
} else {
|
||||
let v = [];
|
||||
this.uploadList.forEach(e => {
|
||||
v.push(e.url);
|
||||
});
|
||||
this.$emit("input", v);
|
||||
this.$emit("on-change", v);
|
||||
}
|
||||
},
|
||||
setData(v, init) {
|
||||
if (typeof v == "string") {
|
||||
// 单张
|
||||
if (this.multiple) {
|
||||
this.$Message.warning("多张上传仅支持数组数据类型");
|
||||
return;
|
||||
}
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
this.uploadList = [];
|
||||
let item = {
|
||||
url: v,
|
||||
status: "finished"
|
||||
};
|
||||
this.uploadList.push(item);
|
||||
this.$emit("on-change", v);
|
||||
} else if (typeof v == "object") {
|
||||
// 多张
|
||||
if (!this.multiple) {
|
||||
this.$Message.warning("单张上传仅支持字符串数据类型");
|
||||
return;
|
||||
}
|
||||
this.uploadList = [];
|
||||
if (v.length > this.limit) {
|
||||
for (let i = 0; i < this.limit; i++) {
|
||||
let item = {
|
||||
url: v[i],
|
||||
status: "finished"
|
||||
};
|
||||
this.uploadList.push(item);
|
||||
}
|
||||
this.$emit("on-change", v.slice(0, this.limit));
|
||||
if (init) {
|
||||
this.$emit("input", v.slice(0, this.limit));
|
||||
}
|
||||
this.$Message.warning("最多只能上传" + this.limit + "张图片");
|
||||
} else {
|
||||
v.forEach(e => {
|
||||
let item = {
|
||||
url: e,
|
||||
status: "finished"
|
||||
};
|
||||
this.uploadList.push(item);
|
||||
});
|
||||
this.$emit("on-change", v);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.setData(val);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.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: 5px;
|
||||
}
|
||||
.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);
|
||||
}
|
||||
.upload-list:hover .upload-list-cover {
|
||||
display: block;
|
||||
}
|
||||
.upload-list-cover i {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
margin: 0 2px;
|
||||
}
|
||||
.list-group {
|
||||
display: inline-block;
|
||||
}
|
||||
.thumb-ghost {
|
||||
opacity: 0.5;
|
||||
background: #c8ebfb;
|
||||
}
|
||||
</style>
|
||||
|
||||
183
seller/src/views/my-components/map/index.vue
Normal file
183
seller/src/views/my-components/map/index.vue
Normal file
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<div class="map">
|
||||
<Modal
|
||||
v-model="showMap"
|
||||
title="选择地址"
|
||||
width="800"
|
||||
>
|
||||
<div class="address">{{addrContent.address}}</div>
|
||||
<div id="map-container"></div>
|
||||
|
||||
<div class="search-con">
|
||||
<Input placeholder="输入关键字搜索" id="input-map" v-model="mapSearch"/>
|
||||
<ul>
|
||||
<li v-for="(tip, index) in tips" :key="index" @click="selectAddr(tip.location)">
|
||||
<p>{{tip.name}}</p>
|
||||
<p>{{tip.district + tip.address}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<Button type="default" @click="showMap = false">取消</Button>
|
||||
<Button type="primary" :loading="loading" @click="ok">确定</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import {getRegion} from '@/api/common.js'
|
||||
export default {
|
||||
name:'map',
|
||||
data() {
|
||||
return {
|
||||
showMap:false, // 地图显隐
|
||||
mapSearch:'', // 地图搜索
|
||||
map:null, // 初始化地图
|
||||
autoComplete:null, // 初始化搜索方法
|
||||
geocoder:null, // 初始化地理、坐标转化
|
||||
positionPicker:null, // 地图拖拽选点
|
||||
tips:[], //搜索关键字列表
|
||||
addrContent:{}, // 回显地址信息
|
||||
loading:false, // 加载状态
|
||||
};
|
||||
},
|
||||
watch:{
|
||||
mapSearch:function(val){
|
||||
this.searchOfMap(val)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
ok(){ // 确定选择
|
||||
|
||||
this.loading = true
|
||||
|
||||
const codeObj = {}
|
||||
const params = {
|
||||
cityCode: this.addrContent.regeocode.addressComponent.citycode,
|
||||
townName: this.addrContent.regeocode.addressComponent.township
|
||||
}
|
||||
getRegion(params).then(res=>{
|
||||
if(res.code == 200) {
|
||||
this.addrContent.addr = res.result.name.replace(/,/g," ")
|
||||
this.addrContent.addrId = res.result.id
|
||||
this.loading = false
|
||||
this.showMap = false;
|
||||
this.$emit('getAddress',this.addrContent);
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
init() {
|
||||
AMapLoader.load({
|
||||
key: "b440952723253aa9fe483e698057bf7d", // 申请好的Web端开发者Key,首次调用 load 时必填
|
||||
version: "", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||||
plugins: [
|
||||
"AMap.ToolBar",
|
||||
"AMap.Autocomplete",
|
||||
"AMap.PlaceSearch",
|
||||
"AMap.Geolocation",
|
||||
'AMap.Geocoder'
|
||||
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
|
||||
"AMapUI": { // 是否加载 AMapUI,缺省不加载
|
||||
"version": '1.1', // AMapUI 缺省 1.1
|
||||
"plugins":['misc/PositionPicker'], // 需要加载的 AMapUI ui插件
|
||||
},
|
||||
})
|
||||
.then((AMap) => {
|
||||
let that = this;
|
||||
this.map = new AMap.Map("map-container",{
|
||||
zoom:12
|
||||
});
|
||||
that.map.addControl(new AMap.ToolBar());
|
||||
that.map.addControl(new AMap.Autocomplete());
|
||||
that.map.addControl(new AMap.PlaceSearch());
|
||||
that.map.addControl(new AMap.Geocoder());
|
||||
|
||||
// 实例化Autocomplete
|
||||
let autoOptions = {
|
||||
city: "全国"
|
||||
};
|
||||
that.autoComplete = new AMap.Autocomplete(autoOptions); // 搜索
|
||||
that.geocoder = new AMap.Geocoder(autoOptions)
|
||||
|
||||
|
||||
that.positionPicker = new AMapUI.PositionPicker({ // 拖拽选点
|
||||
mode: 'dragMap',
|
||||
map:that.map
|
||||
});
|
||||
that.positionPicker.start()
|
||||
/**
|
||||
*
|
||||
* 所有回显数据,都在positionResult里面
|
||||
* 需要字段可以查找
|
||||
*
|
||||
*/
|
||||
that.positionPicker.on('success', function(positionResult) {
|
||||
that.addrContent = positionResult;
|
||||
});
|
||||
|
||||
})
|
||||
.catch((e) => {});
|
||||
},
|
||||
searchOfMap(val) { // 地图搜索
|
||||
let that = this;
|
||||
this.autoComplete.search(val, function (status, result) {
|
||||
// 搜索成功时,result即是对应的匹配数据
|
||||
if(status == 'complete' && result.info == 'OK'){
|
||||
that.tips = result.tips;
|
||||
}else {
|
||||
that.tips = []
|
||||
}
|
||||
});
|
||||
},
|
||||
selectAddr(location) { // 选择坐标
|
||||
if(!location){
|
||||
this.$Message.warning('请选择正确点位')
|
||||
return false;
|
||||
}
|
||||
const lnglat = [location.lng,location.lat]
|
||||
this.positionPicker.start(lnglat)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
#map-container{
|
||||
width: 500px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.search-con{
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 64px;
|
||||
width: 260px;
|
||||
ul{
|
||||
width: 260px;
|
||||
height: 400px;
|
||||
overflow: scroll;
|
||||
li{
|
||||
padding: 5px;
|
||||
p:nth-child(2){
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
&:hover{
|
||||
background-color:#eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.address{
|
||||
margin-bottom: 10px;
|
||||
// color: $theme_color;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
117
seller/src/views/my-components/tree-table/Checkbox/Checkbox.less
Normal file
117
seller/src/views/my-components/tree-table/Checkbox/Checkbox.less
Normal file
@@ -0,0 +1,117 @@
|
||||
// text
|
||||
@prefixCls: zk-checkbox;
|
||||
// color
|
||||
@border: #dddee1;
|
||||
@hoverBorder: #bcbcbc;
|
||||
@blue: #2d8cf0;
|
||||
|
||||
.@{prefixCls}-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.@{prefixCls} {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
&:hover {
|
||||
.@{prefixCls}__inner {
|
||||
border-color: @hoverBorder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}__inner {
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 1px solid @border;
|
||||
border-radius: 2px;
|
||||
background-color: #ffffff;
|
||||
transition: border-color .2s ease-in-out,background-color .2s ease-in-out;
|
||||
&::after {
|
||||
content: "";
|
||||
display: table;
|
||||
width: 4px;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 4px;
|
||||
border: 2px solid #fff;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
transform: rotate(45deg) scale(0);
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}--indeterminate {
|
||||
.@{prefixCls}__inner {
|
||||
background-color: @blue;
|
||||
border-color: @blue;
|
||||
&::after {
|
||||
content: "";
|
||||
width: 8px;
|
||||
height: 1px;
|
||||
transform: scale(1);
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.@{prefixCls}__inner {
|
||||
border-color: @blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}--checked {
|
||||
.@{prefixCls}__inner {
|
||||
border-color: @blue;
|
||||
background-color: @blue;
|
||||
&::after {
|
||||
content: "";
|
||||
display: table;
|
||||
width: 4px;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 4px;
|
||||
border: 2px solid #ffffff;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
transform: rotate(45deg) scale(1);
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.@{prefixCls}__inner {
|
||||
border-color: @blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}--disabled {
|
||||
cursor: not-allowed;
|
||||
.@{prefixCls}__inner {
|
||||
background-color: #f3f3f3;
|
||||
border-color: @border;
|
||||
&::after {
|
||||
animation-name: none;
|
||||
border-color: #ccc;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.@{prefixCls}__inner {
|
||||
border-color: @border;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<template lang="html">
|
||||
<label :class="`${prefixCls}-wrapper`">
|
||||
<span :class="checkboxClass">
|
||||
<span
|
||||
:class="`${prefixCls}__inner`"
|
||||
@click="toggle"></span>
|
||||
</span>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'zk-checkbox',
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
indeterminate: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
prefixCls: 'zk-checkbox',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
checkboxClass() {
|
||||
return [
|
||||
`${this.prefixCls}`,
|
||||
{
|
||||
[`${this.prefixCls}--disabled`]: this.disabled,
|
||||
[`${this.prefixCls}--checked`]: this.value,
|
||||
[`${this.prefixCls}--indeterminate`]: this.indeterminate,
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
if (this.disabled) {
|
||||
return false;
|
||||
}
|
||||
const value = !this.value;
|
||||
this.$emit('input', value);
|
||||
return this.$emit('on-change', value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" src="./Checkbox.less"></style>
|
||||
170
seller/src/views/my-components/tree-table/Table/Table.less
Normal file
170
seller/src/views/my-components/tree-table/Table/Table.less
Normal file
@@ -0,0 +1,170 @@
|
||||
@import "./font/iconfont";
|
||||
|
||||
// text
|
||||
@prefixCls: zk-table;
|
||||
// color
|
||||
@black: #515a6e;
|
||||
@white: #ffffff;
|
||||
@border: #e9eaec;
|
||||
@hoverRow: #ebf7ff;
|
||||
@backgroundRow: #f8f8f9;
|
||||
|
||||
.@{prefixCls} {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: @white;
|
||||
border: 1px solid @border;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
color: @black;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.@{prefixCls}__header-cell {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.@{prefixCls}__cell-inner {
|
||||
padding: 0px 18px;
|
||||
}
|
||||
|
||||
.@{prefixCls}-default {
|
||||
font-size: 14px;
|
||||
|
||||
.@{prefixCls}__header-row {
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
.@{prefixCls}__body-row {
|
||||
height: 48px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}-small {
|
||||
font-size: 12px;
|
||||
|
||||
.@{prefixCls}__header-row {
|
||||
height: 36px !important;
|
||||
}
|
||||
|
||||
.@{prefixCls}__body-row {
|
||||
height: 40px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}-large {
|
||||
font-size: 16px;
|
||||
|
||||
.@{prefixCls}__header-row {
|
||||
height: 43px !important;
|
||||
}
|
||||
|
||||
.@{prefixCls}__body-row {
|
||||
height: 60px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}__header-wrapper,
|
||||
.@{prefixCls}__footer-wrapper {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.@{prefixCls}__body-wrapper {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.@{prefixCls}__header,
|
||||
.@{prefixCls}__body,
|
||||
.@{prefixCls}__footer {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.@{prefixCls}__header-row {
|
||||
height: 40px;
|
||||
box-sizing: border-box;
|
||||
background-color: @backgroundRow;
|
||||
border-bottom: 1px solid @border;
|
||||
}
|
||||
|
||||
.@{prefixCls}__footer-row {
|
||||
height: 40px;
|
||||
box-sizing: border-box;
|
||||
background-color: @white;
|
||||
border-top: 1px solid @border;
|
||||
}
|
||||
|
||||
.@{prefixCls}__body-row {
|
||||
height: 48px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:not(:first-of-type) {
|
||||
border-top: 1px solid @border;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}__header-cell,
|
||||
.@{prefixCls}__body-cell,
|
||||
.@{prefixCls}__footer-cell {
|
||||
box-sizing: border-box;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.@{prefixCls}--firstProp-header-inner {
|
||||
padding-left: 32px;
|
||||
}
|
||||
|
||||
.@{prefixCls}--empty-row {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.@{prefixCls}--empty-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.@{prefixCls}--center-cell {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.@{prefixCls}--right-cell {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.@{prefixCls}--stripe-row {
|
||||
background-color: @backgroundRow;
|
||||
}
|
||||
|
||||
.@{prefixCls}--row-hover {
|
||||
background-color: @hoverRow;
|
||||
}
|
||||
|
||||
.@{prefixCls}--border-cell {
|
||||
&:not(:last-of-type) {
|
||||
border-right: 1px solid @border;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefixCls}--tree-icon {
|
||||
margin-right: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.@{prefixCls}--expand-inner {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: transform .2s ease-in-out;
|
||||
}
|
||||
|
||||
.@{prefixCls}--expanded-inner {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.@{prefixCls}--expand-content {
|
||||
padding: 20px;
|
||||
}
|
||||
396
seller/src/views/my-components/tree-table/Table/Table.vue
Normal file
396
seller/src/views/my-components/tree-table/Table/Table.vue
Normal file
@@ -0,0 +1,396 @@
|
||||
<template lang="html">
|
||||
<div
|
||||
v-if="columns.length > 0"
|
||||
ref="table"
|
||||
:class="[prefixCls, `${prefixCls}-${size}`, tableClass]">
|
||||
<Spin fix v-if="loading"></Spin>
|
||||
<div
|
||||
v-show="showHeader"
|
||||
ref="header-wrapper"
|
||||
:class="`${prefixCls}__header-wrapper`"
|
||||
@mousewheel="handleEvent('header', $event)">
|
||||
<table-header
|
||||
ref="table-header">
|
||||
</table-header>
|
||||
</div>
|
||||
<div
|
||||
ref="body-wrapper"
|
||||
:style="bodyWrapperStyle"
|
||||
:class="`${prefixCls}__body-wrapper`"
|
||||
@scroll="handleEvent('body', $event)">
|
||||
<table-body
|
||||
ref="table-body"
|
||||
:class="bodyClass">
|
||||
</table-body>
|
||||
</div>
|
||||
<div
|
||||
v-show="showSummary && data.length > 0"
|
||||
ref="footer-wrapper"
|
||||
:class="`${prefixCls}__footer-wrapper`"
|
||||
@mousewheel="handleEvent('footer', $event)">
|
||||
<table-footer
|
||||
ref="table-footer">
|
||||
</table-footer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TableHeader from "./TableHeader";
|
||||
import TableBody from "./TableBody";
|
||||
import TableFooter from "./TableFooter";
|
||||
import { mixins, scrollBarWidth as getSbw } from "./utils";
|
||||
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
||||
// function getBodyData(data, isTreeType, childrenProp, isFold, level = 1) {
|
||||
function getBodyData(
|
||||
primaryKey,
|
||||
oldBodyData,
|
||||
data,
|
||||
isTreeType,
|
||||
childrenProp,
|
||||
isFold,
|
||||
parentFold,
|
||||
level = 1
|
||||
) {
|
||||
let bodyData = [];
|
||||
data.forEach((row, index) => {
|
||||
const children = row[childrenProp];
|
||||
const childrenLen =
|
||||
Object.prototype.toString.call(children).slice(8, -1) === "Array"
|
||||
? children.length
|
||||
: 0;
|
||||
let curIsFold = isFold;
|
||||
if (
|
||||
isFold &&
|
||||
typeof primaryKey === "string" &&
|
||||
Array.isArray(oldBodyData)
|
||||
) {
|
||||
for (let i = 0; i < oldBodyData.length; i++) {
|
||||
const oldRow = oldBodyData[i];
|
||||
if (oldRow[primaryKey] === row[primaryKey]) {
|
||||
if ("_isFold" in oldRow) {
|
||||
curIsFold = oldRow._isFold;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
bodyData.push({
|
||||
_isHover: false,
|
||||
_isExpanded: false,
|
||||
_isChecked: false,
|
||||
_level: level,
|
||||
// _isHide: isFold ? level !== 1 : false,
|
||||
// _isFold: isFold,
|
||||
_isHide: level !== 1 ? isFold && parentFold : false,
|
||||
_isFold: isFold && curIsFold,
|
||||
_childrenLen: childrenLen,
|
||||
_normalIndex: index + 1,
|
||||
...row
|
||||
});
|
||||
if (isTreeType) {
|
||||
if (childrenLen > 0) {
|
||||
// bodyData = bodyData.concat(getBodyData(children, true, childrenProp, isFold, level + 1));
|
||||
bodyData = bodyData.concat(
|
||||
getBodyData(
|
||||
primaryKey,
|
||||
oldBodyData,
|
||||
children,
|
||||
true,
|
||||
childrenProp,
|
||||
isFold,
|
||||
curIsFold,
|
||||
level + 1
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
return bodyData;
|
||||
}
|
||||
|
||||
function initialState(table, expandKey) {
|
||||
return {
|
||||
bodyHeight: "auto",
|
||||
firstProp: expandKey || (table.columns[0] && table.columns[0].key),
|
||||
// bodyData: getBodyData(table.data, table.treeType, table.childrenProp, table.isFold),
|
||||
bodyData: getBodyData(
|
||||
table.primaryKey,
|
||||
table.bodyData,
|
||||
table.data,
|
||||
table.treeType,
|
||||
table.childrenProp,
|
||||
table.isFold,
|
||||
false
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
function initialColumns(table, clientWidth) {
|
||||
let columnsWidth = 0;
|
||||
const minWidthColumns = [];
|
||||
const otherColumns = [];
|
||||
const columns = table.columns.concat();
|
||||
if (table.expandType) {
|
||||
columns.unshift({
|
||||
width: "50"
|
||||
});
|
||||
}
|
||||
if (table.selectable) {
|
||||
columns.unshift({
|
||||
width: "50"
|
||||
});
|
||||
}
|
||||
if (table.showIndex) {
|
||||
columns.unshift({
|
||||
width: "50px",
|
||||
key: "_normalIndex",
|
||||
title: table.indexText
|
||||
});
|
||||
}
|
||||
columns.forEach((column, index) => {
|
||||
let width = "";
|
||||
let minWidth = "";
|
||||
if (!column.width) {
|
||||
if (column.minWidth) {
|
||||
minWidth =
|
||||
typeof column.minWidth === "number"
|
||||
? column.minWidth
|
||||
: parseInt(column.minWidth, 10);
|
||||
} else {
|
||||
minWidth = 80;
|
||||
}
|
||||
minWidthColumns.push({
|
||||
...column,
|
||||
minWidth,
|
||||
_index: index
|
||||
});
|
||||
} else {
|
||||
width =
|
||||
typeof column.width === "number"
|
||||
? column.width
|
||||
: parseInt(column.width, 10);
|
||||
otherColumns.push({
|
||||
...column,
|
||||
width,
|
||||
_index: index
|
||||
});
|
||||
}
|
||||
columnsWidth += minWidth || width;
|
||||
});
|
||||
const scrollBarWidth = getSbw();
|
||||
const totalWidth = columnsWidth + scrollBarWidth;
|
||||
const isScrollX = totalWidth > clientWidth;
|
||||
if (!isScrollX) {
|
||||
const extraWidth = clientWidth - totalWidth;
|
||||
const averageExtraWidth = Math.floor(extraWidth / minWidthColumns.length);
|
||||
minWidthColumns.forEach(column => {
|
||||
column.computedWidth = column.minWidth + averageExtraWidth;
|
||||
});
|
||||
}
|
||||
const tableColumns = otherColumns.concat(minWidthColumns);
|
||||
tableColumns.sort((a, b) => a._index - b._index);
|
||||
return tableColumns;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "TreeTable",
|
||||
mixins: [mixins],
|
||||
components: {
|
||||
TableHeader,
|
||||
TableBody,
|
||||
TableFooter
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
size: {
|
||||
default() {
|
||||
return !this.$IVIEW || this.$IVIEW.size === ""
|
||||
? "default"
|
||||
: this.$IVIEW.size;
|
||||
}
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maxHeight: {
|
||||
type: [String, Number],
|
||||
default: "auto"
|
||||
},
|
||||
stripe: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
treeType: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
childrenProp: {
|
||||
type: String,
|
||||
default: "children"
|
||||
},
|
||||
isFold: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
expandType: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
selectable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
selectType: {
|
||||
type: String,
|
||||
default: "checkbox"
|
||||
},
|
||||
emptyText: {
|
||||
type: String,
|
||||
default: "暂无数据"
|
||||
},
|
||||
showHeader: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showIndex: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
indexText: {
|
||||
type: String,
|
||||
default: "#"
|
||||
},
|
||||
showSummary: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
sumText: {
|
||||
type: String,
|
||||
default: "合计"
|
||||
},
|
||||
primaryKey: String,
|
||||
summaryMethod: Function,
|
||||
showRowHover: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
rowKey: Function,
|
||||
rowClassName: [String, Function],
|
||||
cellClassName: [String, Function],
|
||||
rowStyle: [Object, Function],
|
||||
cellStyle: [Object, Function],
|
||||
expandKey: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
computedWidth: "",
|
||||
computedHeight: "",
|
||||
tableColumns: [],
|
||||
...initialState(this, this.expandKey)
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
bodyWrapperStyle() {
|
||||
return {
|
||||
height: this.bodyHeight
|
||||
};
|
||||
},
|
||||
tableClass() {
|
||||
return {
|
||||
[`${this.prefixCls}--border`]: this.border
|
||||
};
|
||||
},
|
||||
bodyClass() {
|
||||
return {
|
||||
[`${this.prefixCls}--stripe`]: this.stripe
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleEvent(type, $event) {
|
||||
this.validateType(type, ["header", "body", "footer"], "handleEvent");
|
||||
const eventType = $event.type;
|
||||
if (eventType === "scroll") {
|
||||
this.$refs["header-wrapper"].scrollLeft = $event.target.scrollLeft;
|
||||
this.$refs["footer-wrapper"].scrollLeft = $event.target.scrollLeft;
|
||||
}
|
||||
if (eventType === "mousewheel") {
|
||||
const deltaX = $event.deltaX;
|
||||
const $body = this.$refs["body-wrapper"];
|
||||
if (deltaX > 0) {
|
||||
$body.scrollLeft += 10;
|
||||
} else {
|
||||
$body.scrollLeft -= 10;
|
||||
}
|
||||
}
|
||||
return this.$emit(`${type}-${eventType}`, $event);
|
||||
},
|
||||
// computedWidth, computedHeight, tableColumns
|
||||
measure() {
|
||||
this.$nextTick(() => {
|
||||
const { clientWidth, clientHeight } = this.$el;
|
||||
this.computedWidth = clientWidth + 2;
|
||||
this.computedHeight = clientHeight + 2;
|
||||
|
||||
const maxHeight = parseInt(this.maxHeight, 10);
|
||||
if (this.maxHeight !== "auto" && this.computedHeight > maxHeight) {
|
||||
this.bodyHeight = `${maxHeight - 83}px`;
|
||||
}
|
||||
this.tableColumns = initialColumns(this, clientWidth);
|
||||
});
|
||||
},
|
||||
getCheckedProp(key = "index") {
|
||||
if (!this.selectable) {
|
||||
return [];
|
||||
}
|
||||
const checkedIndexs = [];
|
||||
this.bodyData.forEach((item, index) => {
|
||||
if (item._isChecked) {
|
||||
if (key === "index") {
|
||||
checkedIndexs.push(index);
|
||||
} else {
|
||||
checkedIndexs.push(item[key]);
|
||||
}
|
||||
}
|
||||
});
|
||||
return checkedIndexs;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$props: {
|
||||
deep: true,
|
||||
handler() {
|
||||
Object.assign(this.$data, initialState(this, this.expandKey));
|
||||
}
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
this.measure();
|
||||
},
|
||||
mounted() {
|
||||
this.measure();
|
||||
window.addEventListener("resize", this.measure);
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener("resize", this.measure);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" src="./Table.less"></style>
|
||||
327
seller/src/views/my-components/tree-table/Table/TableBody.js
Normal file
327
seller/src/views/my-components/tree-table/Table/TableBody.js
Normal file
@@ -0,0 +1,327 @@
|
||||
import Checkbox from '../Checkbox/Checkbox'; // eslint-disable-line
|
||||
// import Radio from '../Radio/Radio'; // eslint-disable-line
|
||||
import { mixins } from './utils';
|
||||
import { Radio } from 'view-design'; // eslint-disable-line
|
||||
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
export default {
|
||||
name: 'TreeTable__body',
|
||||
mixins: [mixins],
|
||||
components: { Radio },
|
||||
data() {
|
||||
return {
|
||||
radioSelectedIndex: -1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
table() {
|
||||
return this.$parent;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleStatus(type, row, rowIndex, value) {
|
||||
this.validateType(type, ['Expanded', 'Checked', 'Hide', 'Fold'], 'toggleStatus', false);
|
||||
const target = this.table.bodyData[rowIndex];
|
||||
this.table.bodyData.splice(rowIndex, 1, {
|
||||
...target,
|
||||
[`_is${type}`]: typeof value === 'undefined' ? !row[`_is${type}`] : value,
|
||||
});
|
||||
},
|
||||
getChildrenIndex(parentLevel, parentIndex, careFold = true) {
|
||||
const data = this.table.bodyData;
|
||||
let childrenIndex = [];
|
||||
for (let i = parentIndex + 1; i < data.length; i++) {
|
||||
if (data[i]._level <= parentLevel) break;
|
||||
if (data[i]._level - 1 === parentLevel) {
|
||||
childrenIndex.push(i);
|
||||
}
|
||||
}
|
||||
const len = childrenIndex.length; // important!!!
|
||||
if (len > 0) {
|
||||
for (let i = 0; i < len; i++) {
|
||||
const childData = data[childrenIndex[i]];
|
||||
if (
|
||||
childData._childrenLen &&
|
||||
(!careFold || (careFold && !childData._isFold))
|
||||
) {
|
||||
childrenIndex = childrenIndex.concat(
|
||||
this.getChildrenIndex(childData._level, childrenIndex[i], careFold));
|
||||
}
|
||||
}
|
||||
}
|
||||
return childrenIndex;
|
||||
},
|
||||
handleEvent($event, type, data, others) {
|
||||
const certainType = this.validateType(type, ['cell', 'row', 'checkbox', 'icon', 'radio'], 'handleEvent');
|
||||
const eventType = $event ? $event.type : '';
|
||||
const { row, rowIndex, column, columnIndex } = data;
|
||||
const latestData = this.table.bodyData;
|
||||
// Checkbox
|
||||
if (certainType.checkbox) {
|
||||
const { isChecked } = others;
|
||||
this.toggleStatus('Checked', row, rowIndex, isChecked);
|
||||
if (row._childrenLen > 0) {
|
||||
const childrenIndex = this.getChildrenIndex(row._level, rowIndex, false);
|
||||
for (let i = 0; i < childrenIndex.length; i++) {
|
||||
this.toggleStatus('Checked', latestData[childrenIndex[i]], childrenIndex[i], isChecked);
|
||||
}
|
||||
}
|
||||
return this.table.$emit('checkbox-click', latestData[rowIndex], column, columnIndex, $event);
|
||||
}
|
||||
// Radio
|
||||
if (certainType.radio) {
|
||||
this.radioSelectedIndex = rowIndex;
|
||||
return this.table.$emit('radio-click', { row, rowIndex, column, columnIndex, $event });
|
||||
}
|
||||
// Tree's icon
|
||||
if (certainType.icon) {
|
||||
$event.stopPropagation();
|
||||
this.toggleStatus('Fold', row, rowIndex);
|
||||
const childrenIndex = this.getChildrenIndex(row._level, rowIndex);
|
||||
for (let i = 0; i < childrenIndex.length; i++) {
|
||||
this.toggleStatus('Hide', latestData[childrenIndex[i]], childrenIndex[i]);
|
||||
}
|
||||
return this.table.$emit('tree-icon-click', latestData[rowIndex], column, columnIndex, $event);
|
||||
}
|
||||
if (certainType.cell && eventType === 'click') {
|
||||
// 点击扩展单元格
|
||||
if (this.isExpandCell(this.table, columnIndex)) {
|
||||
this.toggleStatus('Expanded', row, rowIndex);
|
||||
return this.table.$emit('expand-cell-click', latestData[rowIndex], column, columnIndex, $event);
|
||||
}
|
||||
}
|
||||
// 行:Hover
|
||||
if (certainType.row && (eventType === 'mouseenter' || eventType === 'mouseleave')) {
|
||||
const { hover } = others;
|
||||
const target = latestData[rowIndex];
|
||||
latestData.splice(rowIndex, 1, {
|
||||
...target,
|
||||
_isHover: hover,
|
||||
});
|
||||
}
|
||||
if (certainType.row && others && others.clickRow && certainType.radio) {
|
||||
this.radioSelectedIndex = rowIndex;
|
||||
return this.table.$emit('radio-click', { row, rowIndex, column, columnIndex, $event });
|
||||
}
|
||||
if (certainType.cell) {
|
||||
return this.table.$emit(`${type}-${eventType}`, latestData[rowIndex], rowIndex, column, columnIndex, $event);
|
||||
}
|
||||
return this.table.$emit(`${type}-${eventType}`, latestData[rowIndex], rowIndex, $event);
|
||||
},
|
||||
},
|
||||
render() {
|
||||
// key
|
||||
// function getKey(row, rowIndex) {
|
||||
// const rowKey = this.table.rowKey;
|
||||
// if (rowKey) {
|
||||
// return rowKey.call(null, row, rowIndex);
|
||||
// }
|
||||
// return rowIndex;
|
||||
// }
|
||||
|
||||
// style
|
||||
function getStyle(type, row, rowIndex, column, columnIndex) {
|
||||
const certainType = this.validateType(type, ['cell', 'row'], 'getStyle');
|
||||
const style = this.table[`${type}Style`];
|
||||
if (typeof style === 'function') {
|
||||
if (certainType.row) {
|
||||
return style.call(null, row, rowIndex);
|
||||
}
|
||||
if (certainType.cell) {
|
||||
return style.call(null, row, rowIndex, column, columnIndex);
|
||||
}
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
// className
|
||||
function getClassName(type, row, rowIndex, column, columnIndex) {
|
||||
const certainType = this.validateType(type, ['cell', 'row', 'inner'], 'getClassName');
|
||||
const classList = [];
|
||||
if (column && column.key == "_normalIndex") {
|
||||
classList.push(`${this.prefixCls}--center-cell`);
|
||||
}
|
||||
if (certainType.row || certainType.cell) {
|
||||
const className = this.table[`${type}ClassName`];
|
||||
if (typeof className === 'string') {
|
||||
classList.push(className);
|
||||
} else if (typeof className === 'function') {
|
||||
if (certainType.row) {
|
||||
classList.push(className.call(null, row, rowIndex) || '');
|
||||
}
|
||||
if (certainType.cell) {
|
||||
classList.push(className.call(null, row, rowIndex, column, columnIndex) || '');
|
||||
}
|
||||
}
|
||||
if (certainType.row) {
|
||||
classList.push(`${this.prefixCls}__body-row`);
|
||||
if (this.table.stripe && rowIndex % 2 !== 0) {
|
||||
classList.push(`${this.prefixCls}--stripe-row`);
|
||||
}
|
||||
if (this.table.showRowHover && row._isHover) {
|
||||
classList.push(`${this.prefixCls}--row-hover`);
|
||||
}
|
||||
}
|
||||
if (certainType.cell) {
|
||||
classList.push(`${this.prefixCls}__body-cell`);
|
||||
if (this.table.border) {
|
||||
classList.push(`${this.prefixCls}--border-cell`);
|
||||
}
|
||||
const align = column.align;
|
||||
if (['center', 'right'].indexOf(align) > -1) {
|
||||
classList.push(`${this.prefixCls}--${align}-cell`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (certainType.inner) {
|
||||
classList.push(`${this.prefixCls}__cell-inner`);
|
||||
if (this.isExpandCell(this.table, columnIndex)) {
|
||||
classList.push(`${this.prefixCls}--expand-inner`);
|
||||
if (row._isExpanded) {
|
||||
classList.push(`${this.prefixCls}--expanded-inner`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return classList.join(' ');
|
||||
}
|
||||
|
||||
// 根据type渲染单元格Cell
|
||||
function renderCell(row, rowIndex, column, columnIndex) {
|
||||
// ExpandType
|
||||
if (this.isExpandCell(this.table, columnIndex)) {
|
||||
return <i class='zk-icon zk-icon-angle-right'></i>;
|
||||
}
|
||||
// SelectionType's Checkbox
|
||||
if (this.isSelectionCell(this.table, columnIndex)) {
|
||||
let res = null;
|
||||
if (this.table.selectType === 'checkbox') {
|
||||
let allCheck;
|
||||
let childrenIndex;
|
||||
const hasChildren = row._childrenLen > 0;
|
||||
if (hasChildren) {
|
||||
childrenIndex = this.getChildrenIndex(row._level, rowIndex, false);
|
||||
allCheck = true;
|
||||
for (let i = 0; i < childrenIndex.length; i++) {
|
||||
if (!this.table.bodyData[childrenIndex[i]]._isChecked) {
|
||||
allCheck = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
allCheck = row._isChecked;
|
||||
}
|
||||
let indeterminate = false;
|
||||
if (hasChildren && !allCheck) {
|
||||
for (let i = 0; i < childrenIndex.length; i++) {
|
||||
if (this.table.bodyData[childrenIndex[i]]._isChecked) {
|
||||
indeterminate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// res = <Checkbox
|
||||
// indeterminate={indeterminate}
|
||||
// value={allCheck}
|
||||
// onOn-change={isChecked => this.handleEvent(null, 'checkbox', { row, rowIndex, column, columnIndex }, { isChecked })}>
|
||||
// </Checkbox>;
|
||||
} else {
|
||||
res = <Radio value={this.radioSelectedIndex === rowIndex} on-on-change={() => this.handleEvent(null, 'radio', { row, rowIndex, column, columnIndex })}></Radio>;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Tree's firstProp
|
||||
if (this.table.treeType && this.table.firstProp === column.key) {
|
||||
return <span
|
||||
class={`${this.prefixCls}--level-${row._level}-cell`}
|
||||
style={{
|
||||
marginLeft: `${(row._level - 1) * 24}px`,
|
||||
paddingLeft: row._childrenLen === 0 ? '20px' : '',
|
||||
}}>
|
||||
{row._childrenLen > 0 &&
|
||||
<i
|
||||
class={`${this.prefixCls}--tree-icon zk-icon zk-icon-${row._isFold ? 'plus' : 'minus'}-square-o`}
|
||||
on-click={$event => this.handleEvent($event, 'icon', { row, rowIndex, column, columnIndex }, { isFold: row._isFold })}></i>
|
||||
}
|
||||
{row[column.key] ? row[column.key] : ''}
|
||||
</span>;
|
||||
}
|
||||
// TreeType children's index
|
||||
if (this.table.showIndex && this.table.treeType && column.key === '_normalIndex' && row._level > 1) {
|
||||
return '';
|
||||
}
|
||||
if (column.type === undefined || column.type === 'custom') {
|
||||
return row[column.key];
|
||||
} else if (column.type === 'template') {
|
||||
return this.table.$scopedSlots[column.template]
|
||||
? this.table.$scopedSlots[column.template]({ row, rowIndex, column, columnIndex })
|
||||
: '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// Template
|
||||
return (
|
||||
<table cellspacing="0" cellpadding="0" border="0" class={`${this.prefixCls}__body`}>
|
||||
{/* <colgroup>
|
||||
{this.table.tableColumns.map(column =>
|
||||
<col width={column.computedWidth || column.minWidth || column.width}></col>)
|
||||
}
|
||||
</colgroup> */}
|
||||
<tbody>
|
||||
{ this.table.bodyData.length > 0
|
||||
? this.table.bodyData.map((row, rowIndex) =>
|
||||
[
|
||||
<tr
|
||||
v-show={!row._isHide}
|
||||
key={`table_row_${rowIndex}`}
|
||||
style={getStyle.call(this, 'row', row, rowIndex)}
|
||||
class={getClassName.call(this, 'row', row, rowIndex)}
|
||||
on-click={$event => this.handleEvent($event, 'row', { row, rowIndex }, { clickRow: true })}
|
||||
on-dblclick={$event => this.handleEvent($event, 'row', { row, rowIndex })}
|
||||
on-contextmenu={$event => this.handleEvent($event, 'row', { row, rowIndex })}
|
||||
on-mouseenter={$event => this.handleEvent($event, 'row', { row, rowIndex }, { hover: true })}
|
||||
on-mouseleave={$event => this.handleEvent($event, 'row', { row, rowIndex }, { hover: false })}>
|
||||
{ this.table.tableColumns.map((column, columnIndex) =>
|
||||
column.key ? <td
|
||||
style={getStyle.call(this, 'cell', row, rowIndex, column, columnIndex)}
|
||||
class={getClassName.call(this, 'cell', row, rowIndex, column, columnIndex)}
|
||||
on-click={$event => this.handleEvent($event, 'cell', { row, rowIndex, column, columnIndex })}
|
||||
on-dblclick={$event => this.handleEvent($event, 'cell', { row, rowIndex, column, columnIndex })}
|
||||
on-contextmenu={$event => this.handleEvent($event, 'cell', { row, rowIndex, column, columnIndex })}
|
||||
on-mouseenter={$event => this.handleEvent($event, 'cell', { row, rowIndex, column, columnIndex })}
|
||||
on-mouseleave={$event => this.handleEvent($event, 'cell', { row, rowIndex, column, columnIndex })}>
|
||||
<div class={getClassName.call(this, 'inner', row, rowIndex, column, columnIndex)}>
|
||||
{renderCell.call(this, row, rowIndex, column, columnIndex)}
|
||||
</div>
|
||||
</td>:"")
|
||||
}
|
||||
</tr>,
|
||||
this.table.expandType && row._isExpanded &&
|
||||
<tr
|
||||
key={rowIndex}
|
||||
class={`${this.prefixCls}__body-row ${this.prefixCls}--expand-row`}>
|
||||
<td
|
||||
class={`${this.prefixCls}--expand-content`}
|
||||
colspan={this.table.tableColumns.length}>
|
||||
{this.table.$scopedSlots.expand
|
||||
? this.table.$scopedSlots.expand({ row, rowIndex })
|
||||
: ''
|
||||
}
|
||||
</td>
|
||||
</tr>,
|
||||
])
|
||||
: <tr
|
||||
class={`${this.prefixCls}--empty-row`}>
|
||||
<td
|
||||
class={`${this.prefixCls}__body-cell ${this.prefixCls}--empty-content`}
|
||||
colspan={this.table.tableColumns.length}>
|
||||
{this.table.emptyText}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
import { mixins } from './utils';
|
||||
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
export default {
|
||||
name: 'TreeTable__footer',
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
table() {
|
||||
return this.$parent;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
render() {
|
||||
// 计算各列总和
|
||||
function renderCell({ key }, columnIndex) {
|
||||
if (columnIndex === 0) {
|
||||
return this.table.sumText;
|
||||
}
|
||||
const rows = this.table.bodyData;
|
||||
const values = rows.map(row => Number(row[key]));
|
||||
const precisions = [];
|
||||
let notNumber = true;
|
||||
values.forEach((value) => {
|
||||
if (!isNaN(value)) {
|
||||
notNumber = false;
|
||||
const decimal = value.toString().split('.')[1];
|
||||
precisions.push(decimal ? decimal.length : 0);
|
||||
}
|
||||
});
|
||||
const precision = Math.max.apply(null, precisions);
|
||||
if (!notNumber) {
|
||||
return values.reduce((prev, curr) => {
|
||||
const value = Number(curr);
|
||||
if (!isNaN(value)) {
|
||||
return parseFloat((prev + curr).toFixed(precision));
|
||||
}
|
||||
return prev;
|
||||
}, 0);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// className
|
||||
function getClassName() {
|
||||
const classList = [];
|
||||
classList.push(`${this.prefixCls}__footer-cell`);
|
||||
if (this.table.border) {
|
||||
classList.push(`${this.prefixCls}--border-cell`);
|
||||
}
|
||||
return classList.join(' ');
|
||||
}
|
||||
|
||||
// Template
|
||||
return (
|
||||
<table cellspacing="0" cellpadding="0" border="0" class={ `${this.prefixCls}__footer` }>
|
||||
<colgroup>
|
||||
{ this.table.tableColumns.map(column =>
|
||||
<col width={ column.computedWidth || column.minWidth || column.width }></col>)
|
||||
}
|
||||
</colgroup>
|
||||
<tfoot>
|
||||
<tr class={ `${this.prefixCls}__footer-row` }>
|
||||
{ this.table.tableColumns.map((column, columnIndex) =>
|
||||
<td class={ getClassName.call(this) }>
|
||||
<div class={ `${this.prefixCls}__cell-inner` }>
|
||||
{ this.table.summaryMethod
|
||||
? this.table.summaryMethod(this.table.bodyData, column, columnIndex)
|
||||
: renderCell.call(this, column, columnIndex) }
|
||||
</div>
|
||||
</td>)
|
||||
}
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
);
|
||||
},
|
||||
};
|
||||
108
seller/src/views/my-components/tree-table/Table/TableHeader.js
Normal file
108
seller/src/views/my-components/tree-table/Table/TableHeader.js
Normal file
@@ -0,0 +1,108 @@
|
||||
import Checkbox from "../Checkbox/Checkbox"; // eslint-disable-line
|
||||
import { mixins } from "./utils";
|
||||
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
export default {
|
||||
name: "TreeTable__header",
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
table() {
|
||||
return this.$parent;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleAllChecked(checked) {
|
||||
this.table.bodyData = this.table.bodyData.map(row => ({
|
||||
...row,
|
||||
_isChecked: checked
|
||||
}));
|
||||
}
|
||||
},
|
||||
render() {
|
||||
// className
|
||||
function getClassName(type, { headerAlign, key }) {
|
||||
const certainType = this.validateType(
|
||||
type,
|
||||
["cell", "inner"],
|
||||
"getClassName"
|
||||
);
|
||||
const classList = [];
|
||||
if (key == "_normalIndex") {
|
||||
classList.push(`${this.prefixCls}--center-cell`);
|
||||
}
|
||||
if (certainType.cell) {
|
||||
classList.push(`${this.prefixCls}__header-cell`);
|
||||
if (this.table.border) {
|
||||
classList.push(`${this.prefixCls}--border-cell`);
|
||||
}
|
||||
if (["center", "right"].indexOf(headerAlign) > -1) {
|
||||
classList.push(`${this.prefixCls}--${headerAlign}-cell`);
|
||||
}
|
||||
}
|
||||
if (certainType.inner) {
|
||||
classList.push(`${this.prefixCls}__cell-inner`);
|
||||
if (this.table.treeType && this.table.firstProp === key) {
|
||||
classList.push(`${this.prefixCls}--firstProp-header-inner`);
|
||||
}
|
||||
}
|
||||
return classList.join(" ");
|
||||
}
|
||||
|
||||
// 根据type渲染单元格Label
|
||||
function renderLabel(column, columnIndex) {
|
||||
if (
|
||||
this.isSelectionCell(this.table, columnIndex) &&
|
||||
this.selectType === "checkbox"
|
||||
) {
|
||||
const allCheck = this.table.bodyData.every(row => row._isChecked);
|
||||
const indeterminate =
|
||||
!allCheck && this.table.bodyData.some(row => row._isChecked);
|
||||
return (
|
||||
<Checkbox
|
||||
indeterminate={indeterminate}
|
||||
value={allCheck}
|
||||
onOn-change={checked => this.toggleAllChecked(checked)}
|
||||
></Checkbox>
|
||||
);
|
||||
}
|
||||
return column.title ? column.title : "";
|
||||
}
|
||||
|
||||
// Template
|
||||
return (
|
||||
<table
|
||||
cellspacing="0"
|
||||
cellpadding="0"
|
||||
border="0"
|
||||
class={`${this.prefixCls}__header`}
|
||||
>
|
||||
{/* <colgroup>
|
||||
{this.table.tableColumns.map(column => (
|
||||
<col
|
||||
width={column.computedWidth || column.minWidth || column.width}
|
||||
></col>
|
||||
))}
|
||||
</colgroup> */}
|
||||
<thead>
|
||||
<tr class={`${this.prefixCls}__header-row`}>
|
||||
{
|
||||
this.table.tableColumns.map((column, columnIndex) =>
|
||||
column.key ? (
|
||||
<th class={getClassName.call(this, "cell", column)}>
|
||||
<div class={getClassName.call(this, "inner", column)}>
|
||||
{renderLabel.call(this, column, columnIndex)}
|
||||
</div>
|
||||
</th>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
};
|
||||
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
// icon
|
||||
@font-face {font-family: "iconfont";
|
||||
src: url('iconfont.eot?t=1505310522875'); /* IE9*/
|
||||
src: url('iconfont.eot?t=1505310522875#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAW0AAsAAAAACOQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7kggY21hcAAAAYAAAABuAAABojLtBtFnbHlmAAAB8AAAAa8AAAKA73SzT2hlYWQAAAOgAAAALwAAADYO3fRqaGhlYQAAA9AAAAAcAAAAJAfeA4ZobXR4AAAD7AAAABMAAAAUE+kAAGxvY2EAAAQAAAAADAAAAAwBbAHYbWF4cAAABAwAAAAeAAAAIAEUAF1uYW1lAAAELAAAAUUAAAJtPlT+fXBvc3QAAAV0AAAAQAAAAFryy5h0eJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/s04gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDwzZm7438AQw9zA0AAUZgTJAQAoHgyieJzFkcENwyAUQ98HyqHKKDmEZoEOklOnYOK/RmI+uXSCWDLG/pZAALyALK5iAfthDBxKLfLMO/LCJl+lRqL7fp7y3VuoKprV0KxO0qbyGOy5o/+xxPq9nV6YflNX9DY5fsA/k6Pj+yTpAn3jEO8AAHiclVDNitNQFD7n3slNE9vE5N7kpOn0J0mbKB3DGDMZRGw3bhQXA2LB5TyAbmfjohvBhQvfYEAEoc8wr+EDiK4KPkITU0EcXDmHw3fOgfN9fHygATTf+BUPQMIduA9P4AwAxRxjiw0xysqczdGLNI+UxbMki/QkzvljpFgov6jKlIQubLRwhA+iospyluFJuWCPsPCHiP1B+MKdHbr8I5pBNnpXP2Of0Bsnh/biXv30aKmKiexcdF2377ofOkLTOowd2Ba+Jt/QDFPUnzU79K7Gd9kYu/0sfP6qNxm45+/LN8MZGYjrNcrBxPqydEKn7behL92+frvXCcJeMlV48eNWILvD9Du0hXtgl+wSHIBZnJZLzNKyKgh9paPAdVca260hAxPBMBowz9t1uzUDuT8CswEDDtq8Gr7mADaM4QgetrKRhbozQooWeOrkKJVIojg9ccqqjcT3uBJ6lGNZnUYjnBU+ORbGaeYskM93m+kx4vGUrX5PQXK3kUSSrSS9JFWvFJHCjaIGJCFSugcOLeM6c7f6wyFZf/37+PO6AgD/x/vNnN/A7H8bhF86tmcbAHicY2BkYGAAYl/p/jnx/DZfGbhZGEDg6v0IKwT9/yELA7MEkMvBwAQSBQAZYgnZAHicY2BkYGBu+N/AEMPCAAJAkpEBFbACAEcLAm54nGNhYGBgfsnAwMKAwAAOmwD9AAAAAAAAdgCYAPYBQHicY2BkYGBgZQgEYhBgAmIuIGRg+A/mMwAAES0BcgAAeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicY2BigAAuBuyAlZGJkZmRhZGVkY2BsYI7MS89J1W3KDM9o4S3IKe0WLe4sDSxKFU3ny83Mw+Jy8AAAHSWD8A=') format('woff'),
|
||||
url('iconfont.ttf?t=1505310522875') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
|
||||
url('iconfont.svg?t=1505310522875#iconfont') format('svg'); /* iOS 4.1- */
|
||||
}
|
||||
|
||||
.zk-icon {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.zk-icon-plus-square-o:before { content: "\e631"; }
|
||||
|
||||
.zk-icon-minus-square-o:before { content: "\e632"; }
|
||||
|
||||
.zk-icon-angle-right:before { content: "\e633"; }
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<!--
|
||||
2013-9-30: Created.
|
||||
-->
|
||||
<svg>
|
||||
<metadata>
|
||||
Created by iconfont
|
||||
</metadata>
|
||||
<defs>
|
||||
|
||||
<font id="iconfont" horiz-adv-x="1024" >
|
||||
<font-face
|
||||
font-family="iconfont"
|
||||
font-weight="500"
|
||||
font-stretch="normal"
|
||||
units-per-em="1024"
|
||||
ascent="896"
|
||||
descent="-128"
|
||||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="x" unicode="x" horiz-adv-x="1001"
|
||||
d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
|
||||
t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
|
||||
t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
|
||||
|
||||
|
||||
|
||||
<glyph glyph-name="angle-right" unicode="" d="M384.087 97.474c-7.857 0-15.713 2.997-21.707 8.992-11.989 11.989-11.989 31.426 0 43.415l234.118 234.12-234.118 234.118c-11.988 11.989-11.988 31.427 0 43.416 11.989 11.988 31.426 11.988 43.416 0l255.826-255.827c11.989-11.989 11.989-31.427 0-43.416l-255.826-255.827c-5.995-5.995-13.851-8.992-21.708-8.992z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="plus-square-o" unicode="" d="M810.666667 768H213.333333c-46.933333 0-85.333333-38.4-85.333333-85.333333v-597.333334c0-46.933333 38.4-85.333333 85.333333-85.333333h597.333334c46.933333 0 85.333333 38.4 85.333333 85.333333V682.666667c0 46.933333-38.4 85.333333-85.333333 85.333333z m42.666666-682.666667c0-25.6-17.066667-42.666667-42.666666-42.666666H213.333333c-25.6 0-42.666667 17.066667-42.666666 42.666666V682.666667c0 25.6 17.066667 42.666667 42.666666 42.666666h597.333334c25.6 0 42.666667-17.066667 42.666666-42.666666v-597.333334zM768 384c0-25.6-17.066667-42.666667-42.666667-42.666667H298.666667c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666667h426.666666c25.6 0 42.666667-17.066667 42.666667-42.666667zM512 640c25.6 0 42.666667-17.066667 42.666667-42.666667v-426.666666c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666667 42.666667V597.333333c0 25.6 17.066667 42.666667 42.666667 42.666667z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="minus-square-o" unicode="" d="M810.666667 768H213.333333c-46.933333 0-85.333333-38.4-85.333333-85.333333v-597.333334c0-46.933333 38.4-85.333333 85.333333-85.333333h597.333334c46.933333 0 85.333333 38.4 85.333333 85.333333V682.666667c0 46.933333-38.4 85.333333-85.333333 85.333333z m42.666666-682.666667c0-25.6-17.066667-42.666667-42.666666-42.666666H213.333333c-25.6 0-42.666667 17.066667-42.666666 42.666666V682.666667c0 25.6 17.066667 42.666667 42.666666 42.666666h597.333334c25.6 0 42.666667-17.066667 42.666666-42.666666v-597.333334zM768 384c0-25.6-17.066667-42.666667-42.666667-42.666667H298.666667c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666667h426.666666c25.6 0 42.666667-17.066667 42.666667-42.666667z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
|
||||
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
import mixins from './mixins';
|
||||
import scrollBarWidth from './scrollBarWidth';
|
||||
export {
|
||||
mixins,
|
||||
scrollBarWidth
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
prefixCls: 'zk-table',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
validateType(type, validTypes, funcName, isReturn = true) {
|
||||
if (validTypes.indexOf(type) < 0) throw new Error(`${funcName}'s type must is ${validTypes.join(' or ')}.`);
|
||||
if (isReturn) {
|
||||
const certainType = {};
|
||||
validTypes.forEach((item) => {
|
||||
certainType[item] = item === type;
|
||||
});
|
||||
return certainType;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
isExpandCell(table, columnIndex) {
|
||||
return table.expandType && (
|
||||
(table.showIndex && columnIndex === 1) ||
|
||||
(!table.showIndex && columnIndex === 0)
|
||||
);
|
||||
},
|
||||
isSelectionCell(table, columnIndex) {
|
||||
return table.selectable && (
|
||||
(table.showIndex && table.expandType && columnIndex === 2) ||
|
||||
(!table.showIndex && table.expandType && columnIndex === 1) ||
|
||||
(table.showIndex && !table.expandType && columnIndex === 1) ||
|
||||
(!table.showIndex && !table.expandType && columnIndex === 0)
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
let scrollBarWidth;
|
||||
|
||||
export default function () {
|
||||
if (Vue.prototype.$isServer) return 0;
|
||||
if (scrollBarWidth !== undefined) return scrollBarWidth;
|
||||
|
||||
const outer = document.createElement('div');
|
||||
outer.style.visibility = 'hidden';
|
||||
outer.style.width = '100px';
|
||||
outer.style.position = 'absolute';
|
||||
outer.style.top = '-9999px';
|
||||
document.body.appendChild(outer);
|
||||
|
||||
const widthNoScroll = outer.offsetWidth;
|
||||
outer.style.overflow = 'scroll';
|
||||
|
||||
const inner = document.createElement('div');
|
||||
inner.style.width = '100%';
|
||||
outer.appendChild(inner);
|
||||
|
||||
const widthWithScroll = inner.offsetWidth;
|
||||
outer.parentNode.removeChild(outer);
|
||||
scrollBarWidth = widthNoScroll - widthWithScroll;
|
||||
|
||||
return scrollBarWidth;
|
||||
}
|
||||
357
seller/src/views/order/after-order/orderComplaint.vue
Normal file
357
seller/src/views/order/after-order/orderComplaint.vue
Normal file
@@ -0,0 +1,357 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row @keydown.enter.native="handleSearch">
|
||||
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
|
||||
<Form-item label="会员名称" prop="memberName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.memberName"
|
||||
clearable
|
||||
placeholder="请输入会员名称"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="订单号" prop="orderSn">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.orderSn"
|
||||
clearable
|
||||
placeholder="请输入商品名"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="状态" prop="status">
|
||||
<Select v-model="searchForm.status" placeholder="请选择" clearable style="width: 200px">
|
||||
<Option value="NEW">新投诉</Option>
|
||||
<Option value="CANCEL">已撤销</Option>
|
||||
<Option value="WAIT_APPEAL">待申诉</Option>
|
||||
<Option value="COMMUNICATION">对话中</Option>
|
||||
<Option value="WAIT_ARBITRATION">等待仲裁</Option>
|
||||
<Option value="COMPLETE">已完成</Option>
|
||||
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
<Modal
|
||||
:title="modalTitle"
|
||||
v-model="modalVisible"
|
||||
:mask-closable="false"
|
||||
:width="500"
|
||||
>
|
||||
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
|
||||
<FormItem label="评价内容">
|
||||
<span v-if="content == ''">暂无评价</span>
|
||||
<span v-else>{{content}}</span>
|
||||
</FormItem>
|
||||
<FormItem label="评价图片">
|
||||
<upload-pic-thumb
|
||||
v-model="image"
|
||||
:disable="true"
|
||||
:remove="false"
|
||||
></upload-pic-thumb>
|
||||
</FormItem>
|
||||
<FormItem label="回复内容" prop="reply">
|
||||
<Input v-if="replyStatus == false"
|
||||
v-model="form.reply"
|
||||
type="textarea"
|
||||
maxlength="200"
|
||||
:rows="4"
|
||||
clearable
|
||||
style="width:260px"
|
||||
/>
|
||||
<span v-else>
|
||||
{{form.reply}}
|
||||
</span>
|
||||
</FormItem>
|
||||
<FormItem label="回复图片" prop="replyImage">
|
||||
<upload-pic-thumb v-if="replyStatus == false"
|
||||
v-model="form.replyImage"
|
||||
:limit="5"
|
||||
></upload-pic-thumb>
|
||||
<upload-pic-thumb v-else
|
||||
v-model="form.replyImage"
|
||||
:disable="true"
|
||||
:remove="false"
|
||||
></upload-pic-thumb>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="modalVisible = false">取消</Button>
|
||||
<Button v-if="replyStatus == false" type="primary" :loading="submitLoading" @click="handleSubmit" >回复
|
||||
</Button
|
||||
>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Member from "@/api/member";
|
||||
import * as API_Order from "@/api/order";
|
||||
import uploadPicThumb from "@/views/my-components/lili/upload-pic-thumb";
|
||||
|
||||
export default {
|
||||
name: "orderComplaint",
|
||||
components: {
|
||||
uploadPicThumb
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
image:[],//评价图片
|
||||
replyStatus:false,//回复状态
|
||||
modalType: 0, // 添加或编辑标识
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
modalTitle: "", // 添加或编辑标题
|
||||
openTip: true, // 显示提示
|
||||
loading: true, // 表单加载状态
|
||||
content: "",//评价内容
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
form: {}, // 表单数据
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
// 表头
|
||||
{
|
||||
title: "会员名称",
|
||||
key: "memberName",
|
||||
minWidth: 120,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
title: "订单编号",
|
||||
key: "orderSn",
|
||||
minWidth: 120,
|
||||
sortType: "desc",
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 120,
|
||||
sortType: "desc",
|
||||
},
|
||||
{
|
||||
title: "投诉主题",
|
||||
key: "complainTopic",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "投诉时间",
|
||||
key: "createTime",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "投诉状态",
|
||||
key: "complainStatus",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
if (params.row.complainStatus == "NEW") {
|
||||
return h('div', [h('span', { }, '新投诉'),]);
|
||||
} else if (params.row.complainStatus == "CANCEL") {
|
||||
return h('div', [h('span', { }, '已撤销'),]);
|
||||
} else if (params.row.complainStatus == "WAIT_APPEAL") {
|
||||
return h('div', [h('span', { }, '待申诉'),]);
|
||||
} else if (params.row.complainStatus == "COMMUNICATION") {
|
||||
return h('div', [h('span', { }, '对话中'),]);
|
||||
}else if (params.row.complainStatus == "WAIT_ARBITRATION") {
|
||||
return h('div', [h('span', { }, '等待仲裁'),]);
|
||||
}else if (params.row.complainStatus == "COMPLETE") {
|
||||
return h('div', [h('span', { }, '已完成'),]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 200,
|
||||
render: (h, params) => {
|
||||
if(params.row.complainStatus === "COMPLETE"){
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "primary",
|
||||
size: "small",
|
||||
icon: "ios-create-outline",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"详情"
|
||||
),
|
||||
]);
|
||||
}else{
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "primary",
|
||||
size: "small",
|
||||
icon: "ios-create-outline",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"处理"
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
],
|
||||
data: [], // 表格数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
dropDown() {
|
||||
if (this.drop) {
|
||||
this.dropDownContent = "展开";
|
||||
this.dropDownIcon = "ios-arrow-down";
|
||||
} else {
|
||||
this.dropDownContent = "收起";
|
||||
this.dropDownIcon = "ios-arrow-up";
|
||||
}
|
||||
this.drop = !this.drop;
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
API_Order.getComplainPage(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
//回复
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
API_Member.replyMemberReview(this.form.id, this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("回复成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//投诉详情
|
||||
detail(v) {
|
||||
let id = v.id;
|
||||
this.$router.push({
|
||||
name: "order-complaint-detail",
|
||||
query: { id: id },
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
</style>
|
||||
554
seller/src/views/order/after-order/orderComplaintDetail.vue
Normal file
554
seller/src/views/order/after-order/orderComplaintDetail.vue
Normal file
@@ -0,0 +1,554 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<div class="main-content">
|
||||
<div class="div-flow-left">
|
||||
<div class="div-form-default">
|
||||
<h3>投诉信息</h3>
|
||||
<dl>
|
||||
<dt>投诉商品</dt>
|
||||
<dd>{{ complaintInfo.goodsName }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>投诉状态</dt>
|
||||
<dd v-if="complaintInfo.complainStatus =='NEW'">新投诉</dd>
|
||||
<dd v-if="complaintInfo.complainStatus =='CANCEL'">已撤销</dd>
|
||||
<dd v-if="complaintInfo.complainStatus =='WAIT_APPEAL'">待申诉</dd>
|
||||
<dd v-if="complaintInfo.complainStatus =='COMMUNICATION'">对话中</dd>
|
||||
<dd v-if="complaintInfo.complainStatus =='WAIT_ARBITRATION'">等待仲裁</dd>
|
||||
<dd v-if="complaintInfo.complainStatus =='COMPLETE'">已完成</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>投诉时间</dt>
|
||||
<dd>{{ complaintInfo.createTime }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>投诉主题</dt>
|
||||
<dd>{{ complaintInfo.complainTopic }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>投诉内容</dt>
|
||||
<dd>{{ complaintInfo.content }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>投诉凭证</dt>
|
||||
<dd v-if="images === ''">
|
||||
暂无投诉凭证
|
||||
</dd>
|
||||
<dd v-else>
|
||||
<div class="div-img" v-for="(item, index) in images">
|
||||
<img class="complain-img" :src=item>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="div-form-default" v-if="complaintInfo.complainStatus !== 'WAIT_APPEAL'">
|
||||
<h3>商家申诉信息</h3>
|
||||
<dl>
|
||||
<dt>申诉时间</dt>
|
||||
<dd>{{ complaintInfo.appealTime }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>申诉内容</dt>
|
||||
<dd>{{ complaintInfo.appealContent }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>申诉凭证</dt>
|
||||
<dd v-if="appealImages == ''">
|
||||
暂无申诉凭证
|
||||
</dd>
|
||||
<dd v-else>
|
||||
<div class="div-img" v-for="(item, index) in appealImages">
|
||||
<img class="complain-img" :src=item>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="div-form-default" v-if="complaintInfo.complainStatus === 'WAIT_APPEAL'">
|
||||
<h3>商家申诉</h3>
|
||||
<dl>
|
||||
<dt>申诉内容</dt>
|
||||
<dd>
|
||||
<Input v-model="appeal.appealContent" type="textarea" maxlength="200" :rows="4" clearable style="width:260px" />
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>申诉凭证</dt>
|
||||
<dd>
|
||||
<div class="complain-upload-list" :key="index" v-for="(item,index) in appeal.appealImages">
|
||||
<template v-if="item.status === 'finished'">
|
||||
<img class="complain-img" :src="item.url">
|
||||
<div class="complain-upload-list-cover">
|
||||
<Icon type="ios-eye-outline" @click.native="handleView(item.url)"></Icon>
|
||||
<Icon type="ios-trash-outline" @click.native="handleRemove(item)"></Icon>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>
|
||||
</template>
|
||||
</div>
|
||||
<Upload ref="upload" :show-upload-list="false" :on-format-error="handleFormatError" :action="uploadFileUrl" :headers="accessToken" :on-success="handleSuccessGoodsPicture"
|
||||
:format="['jpg','jpeg','png']" :max-size="2048" :on-exceeded-size="handleMaxSize" :before-upload="handleBeforeUpload" multiple 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>
|
||||
<Modal title="View Image" v-model="visible">
|
||||
<img :src="imgName" v-if="visible" style="width: 100%">
|
||||
</Modal>
|
||||
|
||||
<!-- <Input v-model="appeal.appealImages" type="textarea" maxlength="200" :rows="4" clearable
|
||||
style="width:260px"/> -->
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt></dt>
|
||||
<dd>
|
||||
<Button type="primary" :loading="submitLoading" @click="appealSubmit()" style="margin-left: 5px">
|
||||
提交申诉
|
||||
</Button>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="div-form-default">
|
||||
<h3>对话详情</h3>
|
||||
<dl>
|
||||
<dt>对话记录</dt>
|
||||
<dd>
|
||||
<div class="div-content">
|
||||
<p v-for="(item, index) in complaintInfo.orderComplaintCommunications">
|
||||
<span v-if="item.owner === 'STORE'">商家[{{ item.createTime }}]</span>
|
||||
<span v-if="item.owner === 'BUYER'">买家[{{ item.createTime }}]</span>
|
||||
<span v-if="item.owner === 'PLATFORM'">平台[{{ item.createTime }}]</span>
|
||||
{{ item.content }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<dl v-if="complaintInfo.complainStatus!='COMPLETE'">
|
||||
<dt>发送对话</dt>
|
||||
<dd>
|
||||
<Input v-model="params.content" type="textarea" maxlength="200" :rows="4" clearable style="width:260px" />
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt></dt>
|
||||
<dd v-if="complaintInfo.complainStatus != 'COMPLETE'">
|
||||
<div style="text-align: right;width: 45%;margin-top: 10px">
|
||||
<Button type="primary" :loading="submitLoading" @click="handleSubmit" style="margin-left: 5px">
|
||||
回复
|
||||
</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="returnDataList" style="margin-left: 5px">
|
||||
返回列表
|
||||
</Button>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="div-form-default" v-if="complaintInfo.complainStatus === 'COMPLETE'">
|
||||
<h3>仲裁结果</h3>
|
||||
<dl>
|
||||
<dt>仲裁意见</dt>
|
||||
<dd>
|
||||
{{ complaintInfo.arbitrationResult }}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-flow-center">
|
||||
|
||||
</div>
|
||||
<div class="div-flow-right">
|
||||
<div class="div-form-default">
|
||||
<h3>相关商品交易信息</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
<img :src="complaintInfo.goodsImage" height="60px">
|
||||
</dt>
|
||||
<dd>
|
||||
<a>{{ complaintInfo.goodsName }}</a><br>
|
||||
<span>{{ complaintInfo.goodsPrice | unitPrice }} * {{ complaintInfo.num }}(数量)</span>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
<div class="div-form-default">
|
||||
<h3>订单相关信息</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
订单编号
|
||||
</dt>
|
||||
<dd>
|
||||
{{ complaintInfo.orderSn }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
下单时间
|
||||
</dt>
|
||||
<dd>
|
||||
{{ complaintInfo.orderTime }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
订单金额
|
||||
</dt>
|
||||
<dd>
|
||||
{{ complaintInfo.orderPrice }}
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
<div class="div-form-default">
|
||||
<h3>收件人信息</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
收货人
|
||||
</dt>
|
||||
<dd>
|
||||
{{ complaintInfo.consigneeName }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
收货地址
|
||||
</dt>
|
||||
<dd>
|
||||
{{ complaintInfo.consigneeAddressPath }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
收货人手机
|
||||
</dt>
|
||||
<dd>
|
||||
{{ complaintInfo.consigneeMobile }}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Order from "@/api/order";
|
||||
import uploadPicThumb from "@/views/my-components/lili/upload-pic-thumb";
|
||||
import * as API_GOODS from "@/api/goods";
|
||||
export default {
|
||||
name: "orderComplaint",
|
||||
components: {
|
||||
uploadPicThumb,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//展示图片层
|
||||
visible: false,
|
||||
//上传图片路径
|
||||
uploadFileUrl: API_GOODS.uploadFile,
|
||||
accessToken: "", // 验证token
|
||||
id: 0, // 投诉单id
|
||||
complaintInfo: "", // 投诉信息
|
||||
images: [], //会员申诉图片
|
||||
appealImages: [], //商家申诉的图片
|
||||
applyAppealImages: [], //商家申诉表单填写的图片
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
//商家回复内容
|
||||
params: {
|
||||
content: "",
|
||||
complainId: "",
|
||||
},
|
||||
//投诉
|
||||
appeal: {
|
||||
orderComplaintId: "",
|
||||
appealContent: "",
|
||||
appealImages: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.getDetail();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleView(name) {
|
||||
this.imgName = name;
|
||||
this.visible = true;
|
||||
},
|
||||
handleRemove(file) {
|
||||
this.appeal.appealImages = this.appeal.appealImages.filter(
|
||||
(i) => i.url !== file.url
|
||||
);
|
||||
},
|
||||
handleSuccessGoodsPicture(res, file) {
|
||||
if (file.response) {
|
||||
file.url = file.response.result;
|
||||
|
||||
this.appeal.appealImages.push(file);
|
||||
}
|
||||
},
|
||||
handleBeforeUpload() {
|
||||
const check =
|
||||
this.images.images !== undefined && this.images.images.length > 5;
|
||||
if (check) {
|
||||
this.$Notice.warning({
|
||||
title: "Up to five pictures can be uploaded.",
|
||||
});
|
||||
}
|
||||
return !check;
|
||||
},
|
||||
handleFormatError(file) {
|
||||
this.$Notice.warning({
|
||||
title: "图片格式不正确",
|
||||
desc:
|
||||
"File format of " +
|
||||
file.name +
|
||||
" is incorrect, please select jpg or png.",
|
||||
});
|
||||
},
|
||||
handleMaxSize(file) {
|
||||
this.$Notice.warning({
|
||||
title: "超过文件大小限制",
|
||||
desc: "图片 " + file.name + " 不能超过2mb",
|
||||
});
|
||||
},
|
||||
getDetail() {
|
||||
this.loading = true;
|
||||
API_Order.getComplainDetail(this.id).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.complaintInfo = res.result;
|
||||
this.images = (res.result.images || "").split(",");
|
||||
this.appealImages = (res.result.appealImages || "").split(",");
|
||||
}
|
||||
});
|
||||
},
|
||||
//返回列表
|
||||
returnDataList() {
|
||||
this.$router.push({
|
||||
name: "orderComplaint",
|
||||
});
|
||||
},
|
||||
//回复
|
||||
handleSubmit() {
|
||||
if (this.params.content === "") {
|
||||
this.$Message.error("请填写对话内容");
|
||||
return;
|
||||
}
|
||||
this.params.complainId = this.id;
|
||||
API_Order.addOrderComplaint(this.params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("对话成功");
|
||||
this.params.content = "";
|
||||
this.getDetail();
|
||||
}
|
||||
});
|
||||
},
|
||||
//回复
|
||||
appealSubmit() {
|
||||
|
||||
if (this.appeal.appealContent === "") {
|
||||
this.$Message.error("请填写内容");
|
||||
return;
|
||||
}
|
||||
this.appeal.appealImages = this.appeal.appealImages.map(item=> item.url)
|
||||
this.appeal.orderComplaintId = this.id;
|
||||
API_Order.appeal(this.appeal).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("申诉成功");
|
||||
this.getDetail();
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.id = this.$route.query.id;
|
||||
this.getDetail();
|
||||
this.accessToken = {
|
||||
accessToken: this.getStore("accessToken"),
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/deep/ .ivu-col {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.complain-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;
|
||||
}
|
||||
.complain-upload-list img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.complain-upload-list-cover {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.complain-upload-list:hover .complain-upload-list-cover {
|
||||
display: block;
|
||||
}
|
||||
.complain-upload-list-cover i {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
min-height: 600px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.div-flow-left {
|
||||
width: 49%;
|
||||
letter-spacing: normal;
|
||||
display: inline-block;
|
||||
border-right: solid #f5f5f5 1px;
|
||||
|
||||
.div-form-default {
|
||||
width: 97%;
|
||||
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
background-color: #f5f5f5;
|
||||
padding: 6px 0 6px 12px;
|
||||
border-bottom: solid 1px #e7e7e7;
|
||||
}
|
||||
|
||||
dl {
|
||||
font-size: 0;
|
||||
line-height: 30px;
|
||||
clear: both;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-bottom: dotted 1px #e6e6e6;
|
||||
overflow: hidden;
|
||||
|
||||
dt {
|
||||
display: inline-block;
|
||||
width: 13%;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
padding: 15px 1% 15px 0;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
dd {
|
||||
display: inline-block;
|
||||
width: 84%;
|
||||
padding: 15px 0 15px 1%;
|
||||
margin: 0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.div-img {
|
||||
width: 130px;
|
||||
height: 130px;
|
||||
text-align: center;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.div-flow-center {
|
||||
width: 2%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.div-flow-right {
|
||||
width: 49%;
|
||||
vertical-align: top;
|
||||
word-spacing: normal;
|
||||
display: inline-block;
|
||||
|
||||
.div-form-default {
|
||||
width: 97%;
|
||||
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
background-color: #f5f5f5;
|
||||
padding: 6px 0 6px 12px;
|
||||
border-bottom: solid 1px #e7e7e7;
|
||||
}
|
||||
|
||||
dl {
|
||||
font-size: 0;
|
||||
line-height: 30px;
|
||||
clear: both;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-bottom: dotted 1px #e6e6e6;
|
||||
overflow: hidden;
|
||||
|
||||
dt {
|
||||
display: inline-block;
|
||||
width: 13%;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
padding: 15px 1% 15px 0;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
dd {
|
||||
display: inline-block;
|
||||
width: 84%;
|
||||
padding: 15px 0 15px 1%;
|
||||
margin: 0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.complain-img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.div-content {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
height: 150px;
|
||||
}
|
||||
</style>
|
||||
318
seller/src/views/order/after-order/returnGoodsOrder.vue
Normal file
318
seller/src/views/order/after-order/returnGoodsOrder.vue
Normal file
@@ -0,0 +1,318 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<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"
|
||||
clearable
|
||||
placeholder="请输入商品名称"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="会员名称" prop="memberName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.memberName"
|
||||
clearable
|
||||
placeholder="请输入会员名称"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="订单编号" prop="orderSn">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.orderSn"
|
||||
clearable
|
||||
placeholder="请输入订单编号"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
|
||||
<Form-item label="申请时间">
|
||||
<DatePicker
|
||||
v-model="selectDate"
|
||||
type="datetimerange"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
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 class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
>
|
||||
|
||||
<!-- 商品栏目格式化 -->
|
||||
<template slot="goodsSlot" slot-scope="scope">
|
||||
<div style="margin-top: 5px;height: 90px; display: flex;">
|
||||
<div style="">
|
||||
<img :src="scope.row.goodsImage" style="height: 80px;margin-top: 3px">
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 13px;margin-top: 3px;">
|
||||
<div class="div-zoom" >
|
||||
<a>{{scope.row.goodsName}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Order from "@/api/order";
|
||||
|
||||
export default {
|
||||
name: "returnGoodsOrder",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
startDate: "", // 起始时间
|
||||
endDate: "", // 终止时间
|
||||
serviceType:"RETURN_GOODS",
|
||||
orderSn:"",
|
||||
memberName:"",
|
||||
goodsName:""
|
||||
},
|
||||
selectDate: null,
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
sn: "",
|
||||
sellerName: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
billPrice: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
|
||||
{
|
||||
title: "售后单号",
|
||||
key: "sn",
|
||||
minWidth: 150,
|
||||
},
|
||||
{
|
||||
title: "订单号",
|
||||
key: "orderSn",
|
||||
minWidth: 150,
|
||||
},
|
||||
|
||||
{
|
||||
title: "商品",
|
||||
key: "sn",
|
||||
minWidth: 200,
|
||||
slot: "goodsSlot",
|
||||
|
||||
},
|
||||
{
|
||||
title: "申请退款金额",
|
||||
key: "applyRefundPrice",
|
||||
width: 130,
|
||||
sortType: "desc",
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.applyRefundPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "会员名称",
|
||||
key: "memberName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "serviceStatus",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
if (params.row.serviceStatus == "APPLY") {
|
||||
return h('div', [h('span', { }, '申请售后'),]);
|
||||
} else if (params.row.serviceStatus == "PASS") {
|
||||
return h('div', [h('span', { }, '审核通过'),]);
|
||||
} else if (params.row.serviceStatus == "REFUSE") {
|
||||
return h('div', [h('span', { }, '审核拒绝'),]);
|
||||
} else if (params.row.serviceStatus == "BUYER_RETURN") {
|
||||
return h('div', [h('span', { }, '买家退货,待卖家收货'),]);
|
||||
}else if (params.row.serviceStatus == "SELLER_RE_DELIVERY") {
|
||||
return h('div', [h('span', { }, '商家换货/补发'),]);
|
||||
}else if (params.row.serviceStatus == "SELLER_CONFIRM") {
|
||||
return h('div', [h('span', { }, '卖家确认收货'),]);
|
||||
}else if (params.row.serviceStatus == "SELLER_TERMINATION") {
|
||||
return h('div', [h('span', { }, '卖家终止售后'),]);
|
||||
}else if (params.row.serviceStatus == "BUYER_CONFIRM") {
|
||||
return h('div', [h('span', { }, '买家确认收货'),]);
|
||||
}else if (params.row.serviceStatus == "BUYER_CANCEL") {
|
||||
return h('div', [h('span', { }, '买家取消售后'),]);
|
||||
}else if (params.row.serviceStatus == "COMPLETE") {
|
||||
return h('div', [h('span', { }, '完成'),]);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "申请时间",
|
||||
key: "createTime",
|
||||
width: 170
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"查看"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
dropDown() {
|
||||
if (this.drop) {
|
||||
this.dropDownContent = "展开";
|
||||
this.dropDownIcon = "ios-arrow-down";
|
||||
} else {
|
||||
this.dropDownContent = "收起";
|
||||
this.dropDownIcon = "ios-arrow-up";
|
||||
}
|
||||
this.drop = !this.drop;
|
||||
},
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
API_Order.afterSaleOrderPage(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
detail(v) {
|
||||
let sn = v.sn;
|
||||
this.$router.push({
|
||||
name: "return-goods-order-detail",
|
||||
query: { sn: sn },
|
||||
});
|
||||
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
</style>
|
||||
312
seller/src/views/order/after-order/returnMoneyOrder.vue
Normal file
312
seller/src/views/order/after-order/returnMoneyOrder.vue
Normal file
@@ -0,0 +1,312 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<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"
|
||||
clearable
|
||||
placeholder="请输入商品名称"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="会员名称" prop="memberName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.memberName"
|
||||
clearable
|
||||
placeholder="请输入会员名称"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="订单编号" prop="orderSn">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.orderSn"
|
||||
clearable
|
||||
placeholder="请输入订单编号"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
|
||||
<Form-item label="申请时间">
|
||||
<DatePicker
|
||||
v-model="selectDate"
|
||||
type="datetimerange"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
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 class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
>
|
||||
|
||||
<!-- 商品栏目格式化 -->
|
||||
<template slot="goodsSlot" slot-scope="scope">
|
||||
<div style="margin-top: 5px;height: 90px; display: flex;">
|
||||
<div style="">
|
||||
<img :src="scope.row.goodsImage" style="height: 80px;margin-top: 3px">
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 13px;margin-top: 3px;">
|
||||
<div class="div-zoom" >
|
||||
<a>{{scope.row.goodsName}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Order from "@/api/order";
|
||||
|
||||
export default {
|
||||
name: "returnMoneyOrder",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
startDate: "", // 起始时间
|
||||
endDate: "", // 终止时间
|
||||
serviceType:"RETURN_MONEY",
|
||||
orderSn:"",
|
||||
memberName:"",
|
||||
goodsName:""
|
||||
},
|
||||
selectDate: null,
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
sn: "",
|
||||
sellerName: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
billPrice: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
// 表头
|
||||
{
|
||||
title: "退款编号",
|
||||
key: "sn",
|
||||
minWidth: 150,
|
||||
},
|
||||
{
|
||||
title: "订单号",
|
||||
key: "orderSn",
|
||||
minWidth: 150,
|
||||
},
|
||||
|
||||
{
|
||||
title: "商品",
|
||||
key: "sn",
|
||||
minWidth: 250,
|
||||
sortable: false,
|
||||
slot: "goodsSlot",
|
||||
},
|
||||
{
|
||||
title: "申请退款金额",
|
||||
key: "applyRefundPrice",
|
||||
width: 130,
|
||||
sortType: "desc",
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.applyRefundPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "会员",
|
||||
key: "memberName",
|
||||
minWidth: 130,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: "申请时间",
|
||||
key: "createTime",
|
||||
width: 170
|
||||
},
|
||||
{
|
||||
title: "售后状态",
|
||||
key: "serviceStatus",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
if (params.row.serviceStatus == "APPLY") {
|
||||
return h('div', [h('span', { }, '申请售后'),]);
|
||||
} else if (params.row.serviceStatus == "PASS") {
|
||||
return h('div', [h('span', { }, '审核通过'),]);
|
||||
} else if (params.row.serviceStatus == "REFUSE") {
|
||||
return h('div', [h('span', { }, '审核拒绝'),]);
|
||||
} else if (params.row.serviceStatus == "BUYER_RETURN") {
|
||||
return h('div', [h('span', { }, '买家退货,待卖家收货'),]);
|
||||
}else if (params.row.serviceStatus == "SELLER_RE_DELIVERY") {
|
||||
return h('div', [h('span', { }, '商家换货/补发'),]);
|
||||
}else if (params.row.serviceStatus == "SELLER_CONFIRM") {
|
||||
return h('div', [h('span', { }, '卖家确认收货'),]);
|
||||
}else if (params.row.serviceStatus == "SELLER_TERMINATION") {
|
||||
return h('div', [h('span', { }, '卖家终止售后'),]);
|
||||
}else if (params.row.serviceStatus == "BUYER_CONFIRM") {
|
||||
return h('div', [h('span', { }, '买家确认收货'),]);
|
||||
}else if (params.row.serviceStatus == "BUYER_CANCEL") {
|
||||
return h('div', [h('span', { }, '买家取消售后'),]);
|
||||
}else if (params.row.serviceStatus == "WAIT_REFUND") {
|
||||
return h('div', [h('span', { }, '等待平台退款'),]);
|
||||
}else if (params.row.serviceStatus == "COMPLETE") {
|
||||
return h('div', [h('span', { }, '完成'),]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"查看"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
API_Order.afterSaleOrderPage(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
detail(v) {
|
||||
let sn = v.sn;
|
||||
this.$router.push({
|
||||
name: "return-goods-order-detail",
|
||||
query: { sn: sn },
|
||||
});
|
||||
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
</style>
|
||||
697
seller/src/views/order/after-order/reurnGoodsOrderDetail.vue
Normal file
697
seller/src/views/order/after-order/reurnGoodsOrderDetail.vue
Normal file
@@ -0,0 +1,697 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<div class="main-content">
|
||||
<div class="div-flow-left">
|
||||
<div class="div-form-default">
|
||||
<h3>售后申请</h3>
|
||||
<dl>
|
||||
<dt>售后状态</dt>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='APPLY'">申请售后</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='PASS'">申请通过</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='REFUSE'">申请拒绝</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='BUYER_RETURN'">买家退货,待卖家收货</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='SELLER_RE_DELIVERY'">商家换货</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='SELLER_CONFIRM'">卖家确认收货</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='SELLER_TERMINATION'">卖家终止售后</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='BUYER_CONFIRM'">买家确认收货</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='BUYER_CANCEL'">买家取消售后</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='WAIT_REFUND'">等待平台退款</dd>
|
||||
<dd v-if="afterSaleInfo.serviceStatus =='COMPLETE'">已完成</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>退货退款编号</dt>
|
||||
<dd>{{ afterSaleInfo.sn }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>退货退款原因</dt>
|
||||
<dd>{{ afterSaleInfo.reason }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>申请退款金额</dt>
|
||||
<dd>{{ afterSaleInfo.applyRefundPrice | unitPrice('¥') }}</dd>
|
||||
</dl>
|
||||
<dl v-if="afterSaleInfo.actualRefundPrice">
|
||||
<dt>实际退款金额</dt>
|
||||
<dd>{{ afterSaleInfo.actualRefundPrice | unitPrice('¥') }}</dd>
|
||||
</dl>
|
||||
<dl v-if="afterSaleInfo.refundPoint">
|
||||
<dt>退还积分</dt>
|
||||
<dd>{{ afterSaleInfo.refundPoint }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>退货数量</dt>
|
||||
<dd>{{ afterSaleInfo.num }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>问题描述</dt>
|
||||
<dd>{{ afterSaleInfo.problemDesc }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>凭证</dt>
|
||||
<dd v-if="afterSaleImage == ''">
|
||||
暂无凭证
|
||||
</dd>
|
||||
<dd v-else>
|
||||
<div class="div-img" @click="()=>{picFile=item; picVisible = true}"
|
||||
v-for="(item, index) in afterSaleImage" :key="index">
|
||||
<img class="complain-img" :src="item">
|
||||
|
||||
</div>
|
||||
|
||||
<Modal footer-hide mask-closable v-model="picVisible">
|
||||
<img :src="picFile" alt="无效的图片链接" style="width: 100%; margin: 0 auto; display: block"/>
|
||||
</Modal>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="div-form-default" v-if="afterSaleInfo.serviceStatus=='APPLY'">
|
||||
<h3>商家处理意见</h3>
|
||||
<dl>
|
||||
<dt>商家</dt>
|
||||
<dd>
|
||||
<div class="div-content">
|
||||
{{ afterSaleInfo.storeName }}
|
||||
</div>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>是否同意</dt>
|
||||
<dd>
|
||||
<div class="div-content">
|
||||
<RadioGroup v-model="params.serviceStatus">
|
||||
<Radio label="PASS">
|
||||
<span>同意</span>
|
||||
</Radio>
|
||||
<Radio label="REFUSE">
|
||||
<span>拒绝</span>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>申请退款金额</dt>
|
||||
<dd>{{ afterSaleInfo.applyRefundPrice | unitPrice('¥') }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>实际退款金额</dt>
|
||||
<dd>
|
||||
<Input v-model="params.actualRefundPrice" style="width:260px"/>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>备注信息</dt>
|
||||
<dd>
|
||||
<Input v-model="params.remark" type="textarea" maxlength="200" :rows="4" clearable
|
||||
style="width:260px"/>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt></dt>
|
||||
<dd>
|
||||
<div style="text-align: right;width: 45%;margin-top: 10px">
|
||||
<Button type="primary" :loading="submitLoading" @click="handleSubmit" style="margin-left: 5px">
|
||||
确定
|
||||
</Button>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="div-form-default" v-if="afterSaleInfo.serviceStatus !='APPLY'">
|
||||
<h3>商家处理</h3>
|
||||
<dl>
|
||||
<dt>商家</dt>
|
||||
<dd>
|
||||
<div class="div-content">
|
||||
{{ afterSaleInfo.storeName }}
|
||||
</div>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>审核结果</dt>
|
||||
<dd>
|
||||
<div class="div-content">
|
||||
<span v-if="params.serviceStatus=='PASS'">
|
||||
审核通过
|
||||
</span>
|
||||
<span v-else>
|
||||
审核拒绝
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>备注信息</dt>
|
||||
<dd>
|
||||
{{ afterSaleInfo.auditRemark }}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-flow-center">
|
||||
|
||||
</div>
|
||||
<div class="div-flow-right">
|
||||
<div class="div-form-default">
|
||||
<h3>相关商品交易信息</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
<img :src="afterSaleInfo.goodsImage" height="60px">
|
||||
</dt>
|
||||
<dd>
|
||||
<a>{{ afterSaleInfo.goodsName }}</a><br>
|
||||
<span>{{ afterSaleInfo.num }}(数量)</span><br>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
<div class="div-form-default">
|
||||
<h3>订单相关信息</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
订单编号
|
||||
</dt>
|
||||
<dd>
|
||||
{{ afterSaleInfo.orderSn }}
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
<div class="div-form-default"
|
||||
v-if="afterSaleInfo.serviceStatus =='BUYER_RETURN' || afterSaleInfo.serviceStatus =='COMPLETE' && afterSaleInfo.serviceType !='RETURN_MONEY'">
|
||||
<h3>回寄物流信息</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
物流公司
|
||||
</dt>
|
||||
<dd>
|
||||
{{ afterSaleInfo.mlogisticsName }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
物流单号
|
||||
</dt>
|
||||
<dd>
|
||||
{{ afterSaleInfo.mlogisticsNo }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>操作</dt>
|
||||
<dd>
|
||||
<Button type="info" :loading="submitLoading" @click="sellerConfirmSubmit('PASS')"
|
||||
style="margin-left: 5px" v-if="afterSaleInfo.afterSaleAllowOperationVO.rog">
|
||||
确认收货
|
||||
</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="sellerConfirmSubmit('REFUSE')"
|
||||
style="margin-left: 5px" v-if="afterSaleInfo.afterSaleAllowOperationVO.rog">
|
||||
拒收
|
||||
</Button>
|
||||
<Button type="default" :loading="submitLoading" @click="logisticsBuyer()" style="margin-left: 5px">
|
||||
查询物流
|
||||
</Button>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
<div class="div-form-default"
|
||||
v-if="afterSaleInfo.afterSaleAllowOperationVO.return_goods && afterSaleInfo.serviceType == 'EXCHANGE_GOODS'">
|
||||
<h3>换货</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
换货
|
||||
</dt>
|
||||
<dd>
|
||||
<Button type="primary" :loading="submitLoading" @click="exchangeGoods" style="margin-left: 5px">
|
||||
发货
|
||||
</Button>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="div-form-default"
|
||||
v-if=" afterSaleInfo.serviceType == 'EXCHANGE_GOODS' && afterSaleInfo.serviceStatus =='SELLER_RE_DELIVERY'">
|
||||
<h3>物流信息</h3>
|
||||
<dl>
|
||||
<dt>
|
||||
物流公司
|
||||
</dt>
|
||||
<dd>
|
||||
{{ afterSaleInfo.slogisticsName }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
物流单号
|
||||
</dt>
|
||||
<dd>
|
||||
{{ afterSaleInfo.slogisticsNo }}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>操作</dt>
|
||||
<dd>
|
||||
<Button type="primary" :loading="submitLoading" @click="logisticsSeller()" style="margin-left: 5px">
|
||||
查询物流
|
||||
</Button>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<!-- 订单发货 -->
|
||||
<Modal v-model="modalVisible" width="500px">
|
||||
<p slot="header">
|
||||
<span>订单发货</span>
|
||||
</p>
|
||||
<div>
|
||||
<Form ref="form" :model="form" :label-width="90" :rules="formValidate" style="position:relative">
|
||||
<FormItem label="物流公司" prop="logisticsId">
|
||||
<Select v-model="form.logisticsId" placeholder="请选择" style="width:250px">
|
||||
<Option v-for="(item, i) in checkedLogistics" :key="i" :value="item.id">{{ item.name }}
|
||||
</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem label="物流单号" prop="logisticsNo">
|
||||
<Input v-model="form.logisticsNo" style="width:250px"/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
||||
</div>
|
||||
|
||||
<div slot="footer" style="text-align: right">
|
||||
<Button size="large" @click="orderDeliverCancel">取消</Button>
|
||||
<Button type="success" size="large" @click="orderDeliverySubmit">发货</Button>
|
||||
|
||||
</div>
|
||||
</Modal>
|
||||
<!-- 查询物流 -->
|
||||
<Modal v-model="logisticsModal" width="40">
|
||||
<p slot="header">
|
||||
<span>查询物流</span>
|
||||
</p>
|
||||
<div class="layui-layer-wrap">
|
||||
<dl>
|
||||
<dt>售后单号:</dt>
|
||||
<dd>
|
||||
<div class="text-box">{{ sn }}</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<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">
|
||||
<li v-for="(item,index) in logisticsInfo.traces" :key="index">
|
||||
<span class="time">{{ item.AcceptTime }}</span>
|
||||
<span class="detail">{{ item.AcceptStation }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div slot="footer" style="text-align: right">
|
||||
<Button @click="logisticsClose">取消</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Order from "@/api/order";
|
||||
import uploadPicThumb from "@/views/my-components/lili/upload-pic-thumb";
|
||||
|
||||
export default {
|
||||
name: "orderComplaint",
|
||||
components: {
|
||||
uploadPicThumb,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
picFile: "", // 预览图片地址
|
||||
picVisible: false, // 预览图片
|
||||
sn: "", // 订单号
|
||||
logisticsModal: false, //查询物流模态框
|
||||
logisticsInfo: {}, //物流信息
|
||||
form: { // 物流信息
|
||||
logisticsNo: "",
|
||||
logisticsId: "",
|
||||
}, //换货发货form
|
||||
formValidate: {
|
||||
logisticsNo: [
|
||||
{required: true, message: "发货单号不能为空", trigger: "change"},
|
||||
],
|
||||
logisticsId: [
|
||||
{required: true, message: "请选择物流公司", trigger: "blur"},
|
||||
],
|
||||
},
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
afterSaleInfo: { // 售后信息
|
||||
afterSaleAllowOperationVO: {
|
||||
return_goods: false,
|
||||
},
|
||||
},
|
||||
afterSaleImage: [], //会员申诉图片
|
||||
appealImages: [], //商家申诉的图片
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
checkedLogistics: [], //选中的物流公司集合
|
||||
//商家处理意见
|
||||
params: {
|
||||
serviceStatus: "PASS",
|
||||
remark: "",
|
||||
actualRefundPrice: 0,
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
$route(to, from) {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getDetail() {
|
||||
this.loading = true;
|
||||
API_Order.afterSaleOrderDetail(this.sn).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.afterSaleInfo = res.result;
|
||||
this.afterSaleImage = (res.result.afterSaleImage || "").split(",");
|
||||
this.params.actualRefundPrice = res.result.flowPrice;
|
||||
}
|
||||
});
|
||||
},
|
||||
//换货弹出框
|
||||
exchangeGoods() {
|
||||
API_Order.getLogisticsChecked().then((res) => {
|
||||
if (res.success) {
|
||||
this.checkedLogistics = res.result;
|
||||
this.modalVisible = true;
|
||||
this.getDetail();
|
||||
}
|
||||
});
|
||||
},
|
||||
orderDeliverCancel() {
|
||||
this.modalVisible = false;
|
||||
},
|
||||
//商家确认收货
|
||||
sellerConfirmSubmit(type) {
|
||||
let title = "确认收货";
|
||||
let content = "请确认已经收到退货货物?";
|
||||
let message = "收货成功";
|
||||
if (type !== "PASS") {
|
||||
title = "确认拒收";
|
||||
content = "确认拒收此货物?";
|
||||
message = "拒收成功";
|
||||
this.params.serviceStatus = "REFUSE";
|
||||
}
|
||||
|
||||
this.$Modal.confirm({
|
||||
title: title,
|
||||
content: content,
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
API_Order.afterSaleSellerConfirm(this.sn, this.params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success(message);
|
||||
this.getDetail();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
//查询物流
|
||||
logisticsSeller() {
|
||||
this.logisticsModal = true;
|
||||
API_Order.getSellerDeliveryTraces(this.sn).then((res) => {
|
||||
if (res.success && res.result != null) {
|
||||
this.logisticsInfo = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
//查询物流
|
||||
logisticsBuyer() {
|
||||
this.logisticsModal = true;
|
||||
API_Order.getAfterSaleTraces(this.sn).then((res) => {
|
||||
if (res.success && res.result != null) {
|
||||
this.logisticsInfo = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
//关闭物流弹出框
|
||||
logisticsClose() {
|
||||
this.logisticsModal = false;
|
||||
},
|
||||
|
||||
//换货发货
|
||||
orderDeliverySubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
API_Order.afterSaleSellerDelivery(this.sn, this.form).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("订单发货成功");
|
||||
this.modalVisible = false;
|
||||
this.getDataDetail();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//回复
|
||||
handleSubmit() {
|
||||
if (this.params.remark == "") {
|
||||
this.$Message.error("请输入备注信息");
|
||||
return;
|
||||
}
|
||||
API_Order.afterSaleSellerReview(this.sn, this.params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("审核成功");
|
||||
this.params.remark = "";
|
||||
this.getDetail();
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.sn = this.$route.query.sn;
|
||||
this.getDetail();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ivu-row {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
min-height: 600px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.div-flow-left {
|
||||
width: 49%;
|
||||
letter-spacing: normal;
|
||||
display: inline-block;
|
||||
border-right: solid #f5f5f5 1px;
|
||||
|
||||
.div-form-default {
|
||||
width: 97%;
|
||||
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
background-color: #f5f5f5;
|
||||
padding: 6px 0 6px 12px;
|
||||
border-bottom: solid 1px #e7e7e7;
|
||||
}
|
||||
|
||||
dl {
|
||||
font-size: 0;
|
||||
line-height: 30px;
|
||||
clear: both;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-bottom: dotted 1px #e6e6e6;
|
||||
overflow: hidden;
|
||||
|
||||
dt {
|
||||
display: inline-block;
|
||||
width: 13%;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
padding: 15px 1% 15px 0;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
dd {
|
||||
display: inline-block;
|
||||
width: 84%;
|
||||
padding: 15px 0 15px 1%;
|
||||
margin: 0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dl dt {
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.div-express-log {
|
||||
max-height: 300px;
|
||||
border: solid 1px #e7e7e7;
|
||||
background: #fafafa;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.express-log {
|
||||
margin-right: -10px;
|
||||
margin: 5px;
|
||||
padding: 10px;
|
||||
list-style-type: none;
|
||||
|
||||
.time {
|
||||
width: 30%;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.detail {
|
||||
width: 60%;
|
||||
margin-left: 30px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
li {
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.layui-layer-wrap {
|
||||
dl {
|
||||
border-top: solid 1px #f5f5f5;
|
||||
margin-top: -1px;
|
||||
overflow: hidden;
|
||||
|
||||
dt {
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
display: inline-block;
|
||||
padding: 8px 1% 8px 0;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
dd {
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
display: inline-block;
|
||||
padding: 8px 0 8px 8px;
|
||||
border-left: solid 1px #f5f5f5;
|
||||
|
||||
.text-box {
|
||||
line-height: 40px;
|
||||
color: #333;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.div-img {
|
||||
width: 130px;
|
||||
height: 130px;
|
||||
text-align: center;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.div-flow-center {
|
||||
width: 2%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.div-flow-right {
|
||||
width: 49%;
|
||||
vertical-align: top;
|
||||
word-spacing: normal;
|
||||
display: inline-block;
|
||||
|
||||
.div-form-default {
|
||||
width: 97%;
|
||||
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
background-color: #f5f5f5;
|
||||
padding: 6px 0 6px 12px;
|
||||
border-bottom: solid 1px #e7e7e7;
|
||||
}
|
||||
|
||||
dl {
|
||||
font-size: 0;
|
||||
line-height: 30px;
|
||||
clear: both;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-bottom: dotted 1px #e6e6e6;
|
||||
overflow: hidden;
|
||||
|
||||
dt {
|
||||
display: inline-block;
|
||||
width: 13%;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
padding: 15px 1% 15px 0;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
dd {
|
||||
display: inline-block;
|
||||
width: 84%;
|
||||
padding: 15px 0 15px 1%;
|
||||
margin: 0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.complain-img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
837
seller/src/views/order/order/orderDetail.vue
Normal file
837
seller/src/views/order/order/orderDetail.vue
Normal file
@@ -0,0 +1,837 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col style="width:100%;">
|
||||
<Row style="flex-direction: column;width: 100%;">
|
||||
<Card style="height: 60px">
|
||||
<div style="">
|
||||
<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 @click="orderLog" type="primary">订单日志</Button>
|
||||
<Button v-if="allowOperation.take" @click="orderTake" type="primary">订单核销</Button>
|
||||
<Button v-if="allowOperation.ship" @click="orderDeliver" type="primary">发货</Button>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card style="height: 400px">
|
||||
<div style="width: 30%; float: left; margin-left: 20px">
|
||||
<div class="div-item">
|
||||
<div class="div-item-left">订单号:</div>
|
||||
<div class="div-item-right">{{ orderInfo.order.sn }}</div>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<div class="div-item-left">订单来源:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.order.clientType }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item">
|
||||
<div class="div-item-left">订单状态:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.orderStatusValue }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item">
|
||||
<div class="div-item-left">下单时间:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.order.createTime }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style="width: 30%; float: left; margin-left: 20px">
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == false">
|
||||
<div class="div-item-left">发票信息:</div>
|
||||
<div class="div-item-right">暂无发票信息</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
|
||||
<div class="div-item-left">发票抬头:</div>
|
||||
<div class="div-item-right">{{ orderInfo.receipt.receiptTitle ? orderInfo.receipt.receiptTitle : '暂无' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == true && orderInfo.receipt.taxpayerId">
|
||||
<div class="div-item-left">发票税号:</div>
|
||||
<div class="div-item-right">{{ orderInfo.receipt.taxpayerId ? orderInfo.receipt.taxpayerId : '暂无' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
|
||||
<div class="div-item-left">发票内容:</div>
|
||||
<div class="div-item-right">{{ orderInfo.receipt.receiptContent ? orderInfo.receipt.receiptContent : '暂无' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
|
||||
<div class="div-item-left">发票金额:</div>
|
||||
<div class="div-item-right">{{ orderInfo.receipt.receiptPrice ? orderInfo.receipt.receiptPrice : '暂无' | unitPrice('¥')}}</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
|
||||
<div class="div-item-left">是否开票:</div>
|
||||
<div class="div-item-right">{{ orderInfo.receipt.receiptStatus == 0 ? '未开' : '已开' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 36%; float: left">
|
||||
<div class="div-item">
|
||||
<div class="div-item-left">收货信息:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.order.consigneeName }}
|
||||
{{ orderInfo.order.consigneeMobile }}
|
||||
{{ orderInfo.order.consigneeAddressPath }}
|
||||
{{ orderInfo.order.consigneeDetail }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<div class="div-item-left">支付方式:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.paymentMethodValue }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item">
|
||||
<div class="div-item-left">买家留言:</div>
|
||||
<div class="div-item-right">{{ orderInfo.order.remark }}</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item">
|
||||
<div class="div-item-left">配送方式:</div>
|
||||
<div class="div-item-right">
|
||||
{{
|
||||
orderInfo.deliveryMethodValue
|
||||
? orderInfo.deliveryMethodValue
|
||||
: "暂无配送方式"
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
<Card>
|
||||
<Table :loading="loading" border :columns="columns" :data="data" ref="table" sortable="custom">
|
||||
<!-- 商品栏目格式化 -->
|
||||
<template slot="goodsSlot" slot-scope="scope">
|
||||
<div style="margin-top: 5px; height: 80px; display: flex">
|
||||
<div style="">
|
||||
<img :src="scope.row.image" style="height: 60px; margin-top: 1px; width: 60px" />
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 13px">
|
||||
<div class="div-zoom">
|
||||
<a>{{ scope.row.goodsName }}</a>
|
||||
</div>
|
||||
<div>
|
||||
<span v-for="(item, key) in JSON.parse(scope.row.specs)">
|
||||
<span v-show="key!='images'" style="font-size: 12px;color: #999999;">
|
||||
{{key}} : {{item}}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Table>
|
||||
<div class="goods-total">
|
||||
<ul>
|
||||
<li>
|
||||
<span class="label">商品总额:</span>
|
||||
<span class="txt">{{ orderInfo.order.priceDetailDTO.goodsPrice | unitPrice('¥')}}</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="label">优惠金额:</span>
|
||||
<span class="txt">
|
||||
{{
|
||||
orderInfo.order.priceDetailDTO.couponPrice +
|
||||
orderInfo.order.priceDetailDTO.discountPrice
|
||||
| unitPrice('¥')}}
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="label">运费:</span>
|
||||
<span class="txt">{{ orderInfo.order.freightPrice | unitPrice('¥')}}</span>
|
||||
</li>
|
||||
<li v-if="orderInfo.order.priceDetailDTO.payPoint != 0">
|
||||
<span class="label">使用积分:</span>
|
||||
<span class="txt">{{
|
||||
orderInfo.order.priceDetailDTO.payPoint
|
||||
}}</span>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class="label">应付金额:</span>
|
||||
<span class="txt flowPrice">¥{{ orderInfo.order.flowPrice | unitPrice }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Card>
|
||||
</Row>
|
||||
<Modal v-model="modal" width="530">
|
||||
<p slot="header">
|
||||
<Icon type="edit"></Icon>
|
||||
<span>修改金额</span>
|
||||
</p>
|
||||
<div>
|
||||
<Form ref="modifyPriceForm" :model="modifyPriceForm" label-position="left" :label-width="100" :rules="modifyPriceValidate">
|
||||
<FormItem label="订单金额" prop="orderPrice">
|
||||
<InputNumber style="width:100%;" v-model="modifyPriceForm.orderPrice" size="large" :min="0.01" :max="99999"><span slot="append">元</span></InputNumber>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div slot="footer" style="text-align: right">
|
||||
<Button type="success" size="large" @click="modifyPriceSubmit">调整</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
<!--收件地址弹出框-->
|
||||
<Modal v-model="addressModal" width="530">
|
||||
<p slot="header">
|
||||
<Icon type="edit"></Icon>
|
||||
<span>修改收件信息</span>
|
||||
</p>
|
||||
<div>
|
||||
<Form ref="addressForm" :model="addressForm" label-position="left" :label-width="100" :rules="addressRule">
|
||||
<FormItem label="收件人" prop="consigneeName">
|
||||
<Input v-model="addressForm.consigneeName" size="large" maxlength="20"></Input>
|
||||
</FormItem>
|
||||
<FormItem label="联系方式" prop="consigneeMobile">
|
||||
<Input v-model="addressForm.consigneeMobile" size="large" maxlength="11"></Input>
|
||||
</FormItem>
|
||||
<FormItem label="地址信息" prop="consigneeAddressPath">
|
||||
<Input v-model="addressForm.consigneeAddressPath" disabled style="width: 325px" v-if="showRegion == false" />
|
||||
<Button v-if="showRegion == false" size="small" @click="regionClick" :loading="submitLoading" type="primary" style="margin-left: 8px">修改
|
||||
</Button>
|
||||
<region style="width: 400px" @selected="selectedRegion" v-if="showRegion == true" />
|
||||
</FormItem>
|
||||
<FormItem label="详细地址" prop="consigneeDetail">
|
||||
<Input v-model="addressForm.consigneeDetail" size="large" maxlength="11"></Input>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div slot="footer" style="text-align: right">
|
||||
<Button type="success" size="large" @click="editAddressSubmit">修改</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
<!-- 订单核销 -->
|
||||
<Modal v-model="orderTakeModal" width="530">
|
||||
<p slot="header">
|
||||
<Icon type="edit"></Icon>
|
||||
<span>订单核销</span>
|
||||
</p>
|
||||
<div>
|
||||
<Form ref="orderTakeForm" :model="orderTakeForm" label-position="left" :label-width="100" :rules="orderTakeValidate">
|
||||
<FormItem label="核销码" prop="qrCode">
|
||||
<Input v-model="orderTakeForm.qrCode" size="large" maxlength="10"></Input>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div slot="footer" style="text-align: right">
|
||||
<Button type="success" size="large" @click="orderTakeSubmit">核销</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
<!-- 订单日志 -->
|
||||
<Modal v-model="orderLogModal" width="60">
|
||||
<p slot="header">
|
||||
<span>订单日志</span>
|
||||
</p>
|
||||
<div class="order-log-div">
|
||||
<Table :loading="loading" border :columns="orderLogColumns" :data="orderLogData" ref="table" sortable="custom"></Table>
|
||||
</div>
|
||||
|
||||
<div slot="footer" style="text-align: right">
|
||||
<Button @click="handelCancel">取消</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
<!-- 查询物流 -->
|
||||
<Modal v-model="logisticsModal" width="40">
|
||||
<p slot="header">
|
||||
<span>查询物流</span>
|
||||
</p>
|
||||
<div class="layui-layer-wrap">
|
||||
<dl>
|
||||
<dt>订单号:</dt>
|
||||
<dd>
|
||||
<div class="text-box">{{ sn }}</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<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">
|
||||
<li v-for="(item, index) in logisticsInfo.traces" :key="index">
|
||||
<span class="time">{{ item.AcceptTime }}</span>
|
||||
<span class="detail">{{ item.AcceptStation }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div slot="footer" style="text-align: right">
|
||||
<Button @click="logisticsClose">取消</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
<!-- 订单发货 -->
|
||||
<Modal v-model="orderDeliverModal" width="500px">
|
||||
<p slot="header">
|
||||
<span>订单发货</span>
|
||||
</p>
|
||||
<div>
|
||||
<Form ref="orderDeliveryForm" :model="orderDeliveryForm" :label-width="90" :rules="orderDeliverFormValidate" style="position: relative">
|
||||
<FormItem label="物流公司" prop="logisticsId">
|
||||
<Select v-model="orderDeliveryForm.logisticsId" placeholder="请选择" style="width: 250px">
|
||||
<Option v-for="(item, i) in checkedLogistics" :key="i" :value="item.id">{{ item.name }}
|
||||
</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem label="物流单号" prop="logisticsNo">
|
||||
<Input v-model="orderDeliveryForm.logisticsNo" style="width: 250px" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div slot="footer" style="text-align: right">
|
||||
<Button size="large" @click="orderDeliverHandelCancel">取消</Button>
|
||||
<Button type="success" size="large" @click="orderDeliverySubmit">发货</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Order from "@/api/order";
|
||||
import liliMap from "@/views/my-components/map/index";
|
||||
import * as RegExp from "@/libs/RegExp.js";
|
||||
import region from "@/views/lili-components/region";
|
||||
|
||||
export default {
|
||||
name: "orderDetail",
|
||||
components: {
|
||||
liliMap,
|
||||
region,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
region: [], //地区
|
||||
regionId: [], //地区id
|
||||
showRegion: false,
|
||||
orderLogInfo: [], //订单日志数据
|
||||
orderLogModal: false, //弹出调整价格框
|
||||
logisticsModal: false, //弹出查询物流框
|
||||
receiptModal: false, //开发票弹出框
|
||||
orderDeliverModal: false, //订单发货弹出框
|
||||
orderTakeModal: false, //订单核销弹出框
|
||||
checkedLogistics: [], //选中的物流公司集合
|
||||
allowOperation: {}, //订单可才做选项
|
||||
logisticsInfo: {
|
||||
shipper: "",
|
||||
}, //物流信息
|
||||
sn: "", //订单编号
|
||||
orderInfo: { // 订单信息
|
||||
order: {
|
||||
priceDetailDTO: {},
|
||||
},
|
||||
},
|
||||
modal: false, //弹出调整价格框
|
||||
searchForm: {
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 100, // 页面大小
|
||||
},
|
||||
//调整价格表单
|
||||
modifyPriceForm: {
|
||||
orderPrice: 0,
|
||||
},
|
||||
//订单核销表单
|
||||
orderTakeForm: {
|
||||
qrCode: "",
|
||||
},
|
||||
//验证要调整的订单金额
|
||||
orderTakeValidate: {
|
||||
qrCode: [
|
||||
{ required: true, message: "订单核销码不能为空", trigger: "blur" },
|
||||
],
|
||||
},
|
||||
//订单发货
|
||||
orderDeliveryForm: {
|
||||
logisticsNo: "", //发货单号
|
||||
logisticsId: "", //物流公司
|
||||
},
|
||||
//验证要调整的订单金额
|
||||
modifyPriceValidate: {
|
||||
orderPrice: [
|
||||
{ required: true, message: "请输入大于等于0或小于99999的合法金额" },
|
||||
{
|
||||
pattern: /^\d+(\.(([1-9])|(0[1-9])|([\d^0]\d)))?$/,
|
||||
message: "请输入大于0小于9999的合法金额",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
},
|
||||
addressModal: false, //弹出修改收件信息框
|
||||
//收件地址表单
|
||||
addressForm: {
|
||||
consigneeName: "",
|
||||
consigneeMobile: "",
|
||||
consigneeDetail: "",
|
||||
consigneeAddressPath: "",
|
||||
consigneeAddressIdPath: "",
|
||||
},
|
||||
orderDeliverFormValidate: {
|
||||
logisticsNo: [
|
||||
{ required: true, message: "发货单号不能为空", trigger: "change" },
|
||||
],
|
||||
logisticsId: [
|
||||
{ required: true, message: "请选择物流公司", trigger: "blur" },
|
||||
],
|
||||
},
|
||||
addressRule: {
|
||||
consigneeName: [
|
||||
{ required: true, message: "收货人姓名不能为空", trigger: "blur" },
|
||||
],
|
||||
consigneeMobile: [
|
||||
{ required: true, message: "联系方式不能为空", trigger: "blur" },
|
||||
{
|
||||
pattern: RegExp.mobile,
|
||||
trigger: "blur",
|
||||
message: "请输入正确的手机号",
|
||||
},
|
||||
],
|
||||
consigneeDetail: [
|
||||
{ required: true, message: "详细地址不能为空", trigger: "blur" },
|
||||
],
|
||||
},
|
||||
|
||||
columns: [
|
||||
{
|
||||
title: "商品",
|
||||
key: "goodsName",
|
||||
minWidth: 400,
|
||||
slot: "goodsSlot",
|
||||
},
|
||||
{
|
||||
title: "优惠",
|
||||
key: "num",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
let resultText = "";
|
||||
if (params.row.promotionType) {
|
||||
let type = params.row.promotionType.split(",");
|
||||
if (type.indexOf("PINTUAN") != -1) {
|
||||
resultText += "拼团 ";
|
||||
}
|
||||
if (type.indexOf("SECKILL") != -1) {
|
||||
resultText += "秒杀 ";
|
||||
}
|
||||
if (type.indexOf("COUPON") != -1) {
|
||||
resultText += "优惠券 ";
|
||||
}
|
||||
if (type.indexOf("FULL_DISCOUNT") != -1) {
|
||||
resultText += "满减 ";
|
||||
}
|
||||
if (type.indexOf("POINTS_GOODS") != -1) {
|
||||
resultText += "积分商品 ";
|
||||
}
|
||||
}
|
||||
if (resultText === "") {
|
||||
resultText = "暂无未参与任何促销";
|
||||
}
|
||||
return h("div", resultText);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "单价",
|
||||
key: "unitPrice",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
if (!params.row.priceDetailDTO.unitPrice) {
|
||||
return h("div", this.$options.filters.unitPrice(0, "¥"));
|
||||
}
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(
|
||||
params.row.priceDetailDTO.unitPrice,
|
||||
"¥"
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "数量",
|
||||
key: "num",
|
||||
minWidth: 80,
|
||||
},
|
||||
{
|
||||
title: "小计",
|
||||
key: "subTotal",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.subTotal, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
orderLogColumns: [
|
||||
// 表头
|
||||
{
|
||||
title: "时间",
|
||||
key: "createTime",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "操作者",
|
||||
key: "operatorName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "操作类型",
|
||||
key: "operatorType",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "日志",
|
||||
key: "message",
|
||||
minWidth: 200,
|
||||
},
|
||||
],
|
||||
orderLogData: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
//修改地址
|
||||
regionClick() {
|
||||
this.showRegion = true;
|
||||
this.regionId = "";
|
||||
},
|
||||
//弹出订单核销框
|
||||
orderTake() {
|
||||
this.orderTakeModal = true;
|
||||
},
|
||||
//订单核销提交
|
||||
orderTakeSubmit() {
|
||||
this.$refs.orderTakeForm.validate((valid) => {
|
||||
if (valid) {
|
||||
API_Order.orderTake(this.sn, this.orderTakeForm).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("订单核销成功");
|
||||
this.orderTakeModal = false;
|
||||
this.getDataDetail();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//获取订单详细信息
|
||||
getDataDetail() {
|
||||
this.loading = true;
|
||||
API_Order.getOrderDetail(this.sn).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.orderInfo = res.result;
|
||||
this.allowOperation = res.result.allowOperationVO;
|
||||
this.data = res.result.orderItems;
|
||||
this.orderLogData = res.result.orderLogs;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
modifyPrice() {
|
||||
//默认要修改的金额为订单总金额
|
||||
this.modifyPriceForm.orderPrice = this.orderInfo.order.flowPrice;
|
||||
this.modal = true;
|
||||
},
|
||||
//修改订单金额提交
|
||||
modifyPriceSubmit() {
|
||||
this.$refs.modifyPriceForm.validate((valid) => {
|
||||
if (valid) {
|
||||
API_Order.modifyOrderPrice(this.sn, this.modifyPriceForm).then(
|
||||
(res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("修改订单金额成功");
|
||||
this.modal = false;
|
||||
this.getDataDetail();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 选中的地址
|
||||
selectedRegion(val) {
|
||||
this.region = val[1];
|
||||
this.regionId = val[0];
|
||||
},
|
||||
//查询物流
|
||||
logistics() {
|
||||
this.logisticsModal = true;
|
||||
API_Order.getTraces(this.sn).then((res) => {
|
||||
if (res.success && res.result != null) {
|
||||
this.logisticsInfo = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
//关闭物流弹出框
|
||||
logisticsClose() {
|
||||
this.logisticsModal = false;
|
||||
},
|
||||
//订单发货
|
||||
orderDeliver() {
|
||||
API_Order.getLogisticsChecked().then((res) => {
|
||||
if (res.success) {
|
||||
this.checkedLogistics = res.result;
|
||||
this.orderDeliverModal = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
//订单日志取消
|
||||
orderDeliverHandelCancel() {
|
||||
this.orderDeliverModal = false;
|
||||
},
|
||||
//订单发货提交
|
||||
orderDeliverySubmit() {
|
||||
this.$refs.orderDeliveryForm.validate((valid) => {
|
||||
if (valid) {
|
||||
API_Order.orderDelivery(this.sn, this.orderDeliveryForm).then(
|
||||
(res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("订单发货成功");
|
||||
this.orderDeliverModal = false;
|
||||
this.getDataDetail();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//订单日志
|
||||
orderLog() {
|
||||
this.orderLogModal = true;
|
||||
},
|
||||
//订单日志取消
|
||||
handelCancel() {
|
||||
this.orderLogModal = false;
|
||||
},
|
||||
//弹出修改收货地址框
|
||||
editAddress() {
|
||||
this.addressModal = true;
|
||||
this.showRegion = false;
|
||||
this.regionId = this.orderInfo.order.consigneeAddressIdPath;
|
||||
this.region = this.orderInfo.order.consigneeAddressPath;
|
||||
this.addressForm.consigneeName = this.orderInfo.order.consigneeName;
|
||||
this.addressForm.consigneeMobile = this.orderInfo.order.consigneeMobile;
|
||||
this.addressForm.consigneeDetail = this.orderInfo.order.consigneeDetail;
|
||||
this.addressForm.consigneeAddressPath = this.orderInfo.order.consigneeAddressPath;
|
||||
this.addressForm.consigneeAddressIdPath = this.orderInfo.order.consigneeAddressIdPath;
|
||||
},
|
||||
//修改收货地址
|
||||
editAddressSubmit() {
|
||||
if (this.regionId == "") {
|
||||
this.$Message.error("请选择地址");
|
||||
return;
|
||||
}
|
||||
this.addressForm.consigneeAddressPath = this.region;
|
||||
this.addressForm.consigneeAddressIdPath = this.regionId;
|
||||
this.$refs.addressForm.validate((valid) => {
|
||||
if (valid) {
|
||||
API_Order.editOrderConsignee(this.sn, this.addressForm).then(
|
||||
(res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("收货地址修改成功");
|
||||
this.addressModal = false;
|
||||
this.getDataDetail();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.sn = this.$route.query.sn;
|
||||
this.getDataDetail();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
// @import "@/styles/table-common.scss";
|
||||
.order-log-div {
|
||||
line-height: 30px;
|
||||
height: 500px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
dl dt {
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
}
|
||||
.div-express-log {
|
||||
max-height: 300px;
|
||||
border: solid 1px #e7e7e7;
|
||||
background: #fafafa;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.express-log {
|
||||
margin-right: -10px;
|
||||
margin: 5px;
|
||||
padding: 10px;
|
||||
list-style-type: none;
|
||||
.time {
|
||||
width: 30%;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
}
|
||||
.detail {
|
||||
width: 60%;
|
||||
margin-left: 30px;
|
||||
display: inline-block;
|
||||
}
|
||||
li {
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.layui-layer-wrap {
|
||||
dl {
|
||||
border-top: solid 1px #f5f5f5;
|
||||
margin-top: -1px;
|
||||
overflow: hidden;
|
||||
|
||||
dt {
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
display: inline-block;
|
||||
padding: 8px 1% 8px 0;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
dd {
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
display: inline-block;
|
||||
padding: 8px 0 8px 8px;
|
||||
border-left: solid 1px #f5f5f5;
|
||||
|
||||
.text-box {
|
||||
line-height: 40px;
|
||||
color: #333;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flex-card {
|
||||
display: flex;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.card-item {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.flex-card-left {
|
||||
flex: 4;
|
||||
//background: #f8f8f8;
|
||||
}
|
||||
|
||||
.flex-card-right {
|
||||
flex: 6;
|
||||
}
|
||||
|
||||
.search {
|
||||
.operation {
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
.select-clear {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.div-item {
|
||||
line-height: 35px;
|
||||
display: flex;
|
||||
|
||||
> .div-item-left {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
> .div-item-right {
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
.div-status-right {
|
||||
margin-top: 20px;
|
||||
margin-left: 30px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.goods-total {
|
||||
padding: 20px;
|
||||
height: 150px;
|
||||
width: 100%;
|
||||
|
||||
ul {
|
||||
margin-right: 10px;
|
||||
display: block;
|
||||
float: right;
|
||||
list-style-type: none;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.label {
|
||||
float: left;
|
||||
width: 500px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.txt {
|
||||
float: left;
|
||||
width: 130px;
|
||||
text-align: right;
|
||||
font-family: verdana;
|
||||
}
|
||||
|
||||
.flowPrice {
|
||||
color: #cc0000;
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
308
seller/src/views/order/order/orderList.vue
Normal file
308
seller/src/views/order/order/orderList.vue
Normal file
@@ -0,0 +1,308 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row @keydown.enter.native="handleSearch">
|
||||
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
|
||||
<Form-item label="订单编号" prop="orderSn">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.orderSn"
|
||||
clearable
|
||||
placeholder="请输入订单编号"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="会员名称" prop="buyerName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.buyerName"
|
||||
clearable
|
||||
placeholder="请输入会员名称"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="订单状态" prop="orderStatus">
|
||||
<Select v-model="searchForm.orderStatus" placeholder="请选择" clearable style="width: 200px">
|
||||
<Option value="UNPAID">未付款</Option>
|
||||
<Option value="PAID">已付款</Option>
|
||||
<Option value="UNDELIVERED">待发货</Option>
|
||||
<Option value="DELIVERED">已发货</Option>
|
||||
<Option value="COMPLETED">已完成</Option>
|
||||
<Option value="TAKE">待核验</Option>
|
||||
<Option value="CANCELLED">已取消</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="下单时间">
|
||||
<DatePicker
|
||||
v-model="selectDate"
|
||||
type="datetimerange"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
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 class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Order from "@/api/order";
|
||||
|
||||
|
||||
export default {
|
||||
name: "orderList",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
startDate: "", // 起始时间
|
||||
endDate: "", // 终止时间
|
||||
orderSn:"",
|
||||
buyerName:"",
|
||||
orderStatus:""
|
||||
},
|
||||
selectDate: null,
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
sn: "",
|
||||
sellerName: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
billPrice: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
{
|
||||
title: "订单号",
|
||||
key: "sn",
|
||||
minWidth: 240,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: "订单来源",
|
||||
key: "clientType",
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: "订单类型",
|
||||
key: "orderType",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
if (params.row.orderType == "NORMAL") {
|
||||
return h('div', [h('span', { }, '普通订单'),]);
|
||||
} else if (params.row.orderType == "PINTUAN") {
|
||||
return h('div', [h('span', { }, '拼团订单'),]);
|
||||
} else if (params.row.orderType == "GIFT") {
|
||||
return h('div', [h('span', { }, '赠品订单'),]);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "买家名称",
|
||||
key: "memberName",
|
||||
minWidth: 130,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: "订单金额",
|
||||
key: "flowPrice",
|
||||
minWidth: 100,
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.flowPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "订单状态",
|
||||
key: "orderStatus",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
if (params.row.orderStatus == "UNPAID") {
|
||||
return h('div', [h('span', { }, '未付款'),]);
|
||||
} else if (params.row.orderStatus == "PAID") {
|
||||
return h('div', [h('span', { }, '已付款'),]);
|
||||
} else if (params.row.orderStatus == "UNDELIVERED") {
|
||||
return h('div', [h('span', { }, '待发货'),]);
|
||||
}else if (params.row.orderStatus == "DELIVERED") {
|
||||
return h('div', [h('span', { }, '已发货'),]);
|
||||
}else if (params.row.orderStatus == "COMPLETED") {
|
||||
return h('div', [h('span', { }, '已完成'),]);
|
||||
}else if (params.row.orderStatus == "TAKE") {
|
||||
return h('div', [h('span', { }, '待核验'),]);
|
||||
}else if (params.row.orderStatus == "CANCELLED") {
|
||||
return h('div', [h('span', { }, '已取消'),]);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "下单时间",
|
||||
key: "createTime",
|
||||
width: 170,
|
||||
sortable: true,
|
||||
sortType: "desc",
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"查看"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
handleReset() {
|
||||
this.$refs.searchForm.resetFields();
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.selectDate = null;
|
||||
this.searchForm.startDate = "";
|
||||
this.searchForm.endDate = "";
|
||||
// 重新加载数据
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
API_Order.getOrderList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
detail(v) {
|
||||
let sn = v.sn;
|
||||
this.$router.push({
|
||||
name: "order-detail",
|
||||
query: { sn: sn },
|
||||
});
|
||||
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
</style>
|
||||
320
seller/src/views/order/receiptManager/receipt.vue
Normal file
320
seller/src/views/order/receiptManager/receipt.vue
Normal file
@@ -0,0 +1,320 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row @keydown.enter.native="handleSearch">
|
||||
<Form
|
||||
ref="searchForm"
|
||||
:model="searchForm"
|
||||
inline
|
||||
:label-width="70"
|
||||
class="search-form"
|
||||
>
|
||||
<Form-item label="订单编号" prop="orderSn">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.orderSn"
|
||||
clearable
|
||||
placeholder="请输入订单编号"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="会员名称" prop="memberName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.memberName"
|
||||
clearable
|
||||
placeholder="请输入会员名称"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="发票抬头" prop="receiptTitle">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.receiptTitle"
|
||||
clearable
|
||||
placeholder="请输入发票抬头"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="状态" prop="receiptStatus">
|
||||
<Select v-model="searchForm.receiptStatus" placeholder="请选择" clearable style="width: 200px">
|
||||
<Option value="0">未开票</Option>
|
||||
<Option value="1">已开票</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
|
||||
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
>
|
||||
<!-- 订单详情格式化 -->
|
||||
<template slot="orderSlot" slot-scope="scope">
|
||||
<a
|
||||
@click="$router.push({name: 'order-detail',query: {sn: scope.row.orderSn}})">{{scope.row.orderSn}}</a>
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Order from "@/api/order";
|
||||
|
||||
export default {
|
||||
name: "storeBill",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
receiptStatus: "", // 起始时间
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
sn: "",
|
||||
sellerName: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
billPrice: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
{
|
||||
title: "订单号",
|
||||
key: "orderSn",
|
||||
minWidth: 120,
|
||||
slot: "orderSlot",
|
||||
},
|
||||
{
|
||||
title: "会员名称",
|
||||
key: "memberName",
|
||||
minWidth: 90,
|
||||
tooltip: true
|
||||
},
|
||||
|
||||
{
|
||||
title: "发票抬头",
|
||||
key: "receiptTitle",
|
||||
minWidth: 90,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: "纳税人识别号",
|
||||
key: "taxpayerId",
|
||||
minWidth: 100,
|
||||
tooltip: true
|
||||
|
||||
},
|
||||
{
|
||||
title: "发票内容",
|
||||
key: "receiptContent",
|
||||
minWidth: 120,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: "发票金额",
|
||||
key: "billPrice",
|
||||
width: 90,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.receiptPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "发票状态",
|
||||
key: "receiptStatus",
|
||||
width: 90,
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
if(params.row.receiptStatus == 0){
|
||||
return h(
|
||||
"div",
|
||||
"未开票"
|
||||
);
|
||||
}else{
|
||||
return h(
|
||||
"div",
|
||||
"已开票"
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "订单状态",
|
||||
key: "orderStatus",
|
||||
width: 90,
|
||||
render: (h, params) => {
|
||||
if (params.row.orderStatus == "UNPAID") {
|
||||
return h('div', [h('span', { }, '未付款'),]);
|
||||
} else if (params.row.orderStatus == "PAID") {
|
||||
return h('div', [h('span', { }, '已付款'),]);
|
||||
} else if (params.row.orderStatus == "UNDELIVERED") {
|
||||
return h('div', [h('span', { }, '待发货'),]);
|
||||
}else if (params.row.orderStatus == "DELIVERED") {
|
||||
return h('div', [h('span', { }, '已发货'),]);
|
||||
}else if (params.row.orderStatus == "COMPLETED") {
|
||||
return h('div', [h('span', { }, '已完成'),]);
|
||||
}else if (params.row.orderStatus == "TAKE") {
|
||||
return h('div', [h('span', { }, '待核验'),]);
|
||||
}else if (params.row.orderStatus == "CANCELLED") {
|
||||
return h('div', [h('span', { }, '已取消'),]);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 80,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
attrs: {
|
||||
disabled: params.row.orderStatus == "COMPLETED" && params.row.receiptStatus == 0? false : true,
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.invoicing(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"开票"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getData();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getData();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getData();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getData();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getData();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
getData() {
|
||||
this.loading = true;
|
||||
API_Order.getReceiptPage(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
//开发票
|
||||
invoicing(params){
|
||||
this.$Modal.confirm({
|
||||
title: "确认开票",
|
||||
content: "您确认已经开具发票 ?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
API_Order.invoicing(params.id).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("开票成功");
|
||||
}
|
||||
this.$Modal.remove();
|
||||
this.getData();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
</style>
|
||||
410
seller/src/views/promotion/coupon/coupon.vue
Normal file
410
seller/src/views/promotion/coupon/coupon.vue
Normal file
@@ -0,0 +1,410 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Card>
|
||||
<Row>
|
||||
<Form
|
||||
ref="searchForm"
|
||||
:model="searchForm"
|
||||
inline
|
||||
:label-width="100"
|
||||
class="search-form"
|
||||
>
|
||||
<Form-item label="优惠券名称">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.couponName"
|
||||
placeholder="请输入优惠券名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="活动状态" prop="promotionStatus">
|
||||
<Select
|
||||
v-model="searchForm.promotionStatus"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<Option value="NEW">未开始</Option>
|
||||
<Option value="START">已开始/上架</Option>
|
||||
<Option value="END">已结束/下架</Option>
|
||||
<Option value="CLOSE">紧急关闭/作废</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="活动时间">
|
||||
<DatePicker
|
||||
v-model="selectDate"
|
||||
type="daterange"
|
||||
clearable
|
||||
placeholder="选择起始时间"
|
||||
style="width: 200px"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Button
|
||||
@click="handleSearch"
|
||||
type="primary"
|
||||
class="search-btn"
|
||||
icon="ios-search"
|
||||
>搜索</Button
|
||||
>
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="operator padding-row">
|
||||
<Button @click="add" type="primary">添加</Button>
|
||||
<Button @click="delAll">批量下架</Button>
|
||||
<!-- <Button @click="upAll">批量上架</Button> -->
|
||||
</Row>
|
||||
<Row class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
>
|
||||
<template slot-scope="{ row }" slot="action">
|
||||
<Button
|
||||
v-if="row.promotionStatus === 'NEW' || row.promotionStatus === 'CLOSE'"
|
||||
type="primary"
|
||||
size="small"
|
||||
style="margin-right: 10px"
|
||||
@click="edit(row)"
|
||||
>编辑</Button
|
||||
>
|
||||
<Button
|
||||
v-if="row.promotionStatus !== 'CLOSE'"
|
||||
type="error"
|
||||
size="small"
|
||||
@click="remove(row)"
|
||||
>下架</Button
|
||||
>
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<Page
|
||||
:current="searchForm.pageNumber + 1"
|
||||
: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 {
|
||||
getShopCouponList,
|
||||
deleteShopCoupon,
|
||||
updateCouponStatus,
|
||||
} from "@/api/promotion";
|
||||
|
||||
export default {
|
||||
name: "coupon",
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 0, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "startTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
promotionName: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {
|
||||
promotionName: [
|
||||
{ required: true, message: "不能为空", trigger: "blur" },
|
||||
],
|
||||
},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
// 表头
|
||||
{
|
||||
type: "selection",
|
||||
width: 60,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "活动名称",
|
||||
key: "promotionName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "优惠券名称",
|
||||
key: "couponName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "优惠券类型",
|
||||
key: "couponType",
|
||||
minWidth: 50,
|
||||
render: (h, params) => {
|
||||
let text = "未知";
|
||||
if (params.row.couponType == "DISCOUNT") {
|
||||
text = "打折";
|
||||
} else if (params.row.couponType == "PRICE") {
|
||||
text = "减免现金";
|
||||
}
|
||||
return h("div", [text]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "面额",
|
||||
key: "price",
|
||||
minWidth: 40,
|
||||
},
|
||||
{
|
||||
title: "折扣",
|
||||
key: "couponDiscount",
|
||||
minWidth: 40,
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "status",
|
||||
minWidth: 30,
|
||||
render: (h, params) => {
|
||||
let text = "未知",
|
||||
color = "default";
|
||||
if (params.row.promotionStatus == "NEW") {
|
||||
text = "未开始";
|
||||
color = "default";
|
||||
} else if (params.row.promotionStatus == "START") {
|
||||
text = "已开始";
|
||||
color = "green";
|
||||
} else if (params.row.promotionStatus == "END") {
|
||||
text = "已结束";
|
||||
color = "red";
|
||||
} else if (params.row.promotionStatus == "CLOSE") {
|
||||
text = "已关闭";
|
||||
color = "red";
|
||||
}
|
||||
return h("div", [
|
||||
h(
|
||||
"Tag",
|
||||
{
|
||||
props: {
|
||||
color: color,
|
||||
},
|
||||
},
|
||||
text
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "品类描述",
|
||||
key: "scopeType",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
let text = "未知";
|
||||
if (params.row.scopeType == "ALL") {
|
||||
text = "全品类";
|
||||
} else if (params.row.scopeType == "PORTION_GOODS_CATEGORY") {
|
||||
text = "部分商品分类";
|
||||
} else if (params.row.scopeType == "PORTION_GOODS") {
|
||||
text = "指定商品";
|
||||
} else if (params.row.scopeType == "PORTION_SHOP_CATEGORY") {
|
||||
text = "部分店铺分类";
|
||||
}
|
||||
return h("div", [text]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
slot: "action",
|
||||
align: "center",
|
||||
width: 200,
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
add() {
|
||||
this.$router.push({ name: "add-coupon" });
|
||||
},
|
||||
/** 跳转至领取详情页面 */
|
||||
receiveInfo(v) {
|
||||
this.$router.push({ name: "member-receive-coupon", query: { id: v.id } });
|
||||
},
|
||||
info(v) {
|
||||
this.$router.push({ name: "platform-coupon-info", query: { id: v.id } });
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v - 1;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 0;
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
|
||||
this.searchForm.startTime = this.selectDate[0].getTime();
|
||||
this.searchForm.endTime = this.selectDate[1].getTime();
|
||||
} else {
|
||||
this.searchForm.startTime = null;
|
||||
this.searchForm.endTime = null;
|
||||
}
|
||||
// 带多条件搜索参数获取表单数据 请自行修改接口
|
||||
getShopCouponList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
edit(v) {
|
||||
this.$router.push({ name: "add-coupon", query: { id: v.id } });
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认下架",
|
||||
// 记得确认修改此处
|
||||
content: "确认要下架此优惠券么?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
this.loading = false;
|
||||
let params = {
|
||||
couponIds: v.id,
|
||||
promotionStatus: "CLOSE",
|
||||
};
|
||||
// 批量删除
|
||||
updateCouponStatus(params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("下架成功");
|
||||
this.clearSelectAll();
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
upAll() {
|
||||
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.push(e.id);
|
||||
});
|
||||
let params = {
|
||||
couponIds: ids.toString(),
|
||||
promotionStatus: "START",
|
||||
};
|
||||
// 批量上架
|
||||
updateCouponStatus(params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("上架成功");
|
||||
this.clearSelectAll();
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
delAll() {
|
||||
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.push(e.id);
|
||||
});
|
||||
|
||||
let params = {
|
||||
couponIds: ids.toString(),
|
||||
promotionStatus: "CLOSE",
|
||||
};
|
||||
// 批量删除
|
||||
updateCouponStatus(params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("下架成功");
|
||||
this.clearSelectAll();
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
watch: {
|
||||
$route(to, from) {
|
||||
if (to.fullPath == "/promotion/coupon") {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "@/styles/table-common.scss";
|
||||
.search-form {
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
655
seller/src/views/promotion/coupon/couponPublish.vue
Normal file
655
seller/src/views/promotion/coupon/couponPublish.vue
Normal file
@@ -0,0 +1,655 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<Card>
|
||||
<Form ref="form" :model="form" :label-width="120" :rules="formRule">
|
||||
<div class="base-info-item">
|
||||
<h4>基本信息</h4>
|
||||
<div class="form-item-view">
|
||||
<FormItem label="活动名称" prop="promotionName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="form.promotionName"
|
||||
placeholder="活动名称"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="优惠券名称" prop="couponName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="form.couponName"
|
||||
placeholder="优惠券名称"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="优惠券类型" prop="couponType">
|
||||
<Select v-model="form.couponType" style="width: 260px">
|
||||
<Option value="DISCOUNT">打折</Option>
|
||||
<Option value="PRICE">减免现金</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="折扣"
|
||||
prop="discount"
|
||||
v-if="form.couponType == 'DISCOUNT'"
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
v-model="form.couponDiscount"
|
||||
placeholder="折扣"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
<span class="describe">请输入0-10之间数字,可以输入一位小数</span>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="面额"
|
||||
prop="price"
|
||||
v-if="form.couponType == 'PRICE'"
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
v-model="form.price"
|
||||
placeholder="面额"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="活动类型" prop="getType">
|
||||
<Select v-model="form.getType" style="width: 260px">
|
||||
<Option value="FREE">免费领取</Option>
|
||||
<Option value="ACTIVITY">活动赠送</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="发放数量" prop="publishNum">
|
||||
<Input
|
||||
v-model="form.publishNum"
|
||||
placeholder="发放数量"
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
<h4>使用限制</h4>
|
||||
<div class="form-item-view">
|
||||
<FormItem label="消费门槛" prop="consumeThreshold">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="form.consumeThreshold"
|
||||
placeholder="消费门槛"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="领取限制" prop="couponLimitNum">
|
||||
<Input
|
||||
v-model="form.couponLimitNum"
|
||||
placeholder="领取限制"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="有效期" prop="startTime">
|
||||
<DatePicker
|
||||
type="datetime"
|
||||
v-model="form.startTime"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择"
|
||||
:options="options"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
</DatePicker>
|
||||
-
|
||||
<DatePicker
|
||||
type="datetime"
|
||||
v-model="form.endTime"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
:options="options"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
</DatePicker>
|
||||
</FormItem>
|
||||
<FormItem label="使用范围" prop="scopeType">
|
||||
<RadioGroup v-model="form.scopeType">
|
||||
<Radio label="ALL">全品类</Radio>
|
||||
<Radio label="PORTION_GOODS">指定商品</Radio>
|
||||
<Radio label="PORTION_GOODS_CATEGORY">部分商品分类</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
style="width: 100%"
|
||||
v-if="form.scopeType == 'PORTION_GOODS'"
|
||||
>
|
||||
<div style="display: flex; margin-bottom: 10px">
|
||||
<Button type="primary" @click="$refs.skuSelect.open('goods')"
|
||||
>选择商品</Button
|
||||
>
|
||||
<Button
|
||||
type="error"
|
||||
ghost
|
||||
style="margin-left: 10px"
|
||||
@click="delSelectGoods"
|
||||
>批量删除</Button
|
||||
>
|
||||
</div>
|
||||
<Table
|
||||
border
|
||||
:columns="columns"
|
||||
:data="form.promotionGoodsList"
|
||||
@on-selection-change="changeSelect"
|
||||
>
|
||||
<template slot-scope="{ row }" slot="QRCode">
|
||||
<img
|
||||
:src="row.QRCode || '../../../assets/lili.png'"
|
||||
width="50px"
|
||||
height="50px"
|
||||
alt=""
|
||||
/>
|
||||
</template>
|
||||
</Table>
|
||||
</FormItem>
|
||||
|
||||
<FormItem v-if="form.scopeType == 'PORTION_GOODS_CATEGORY'">
|
||||
<Cascader @on-change="getGoodsCategory" :data="goodsCategoryList" style="width:300px;" v-model="form.scopeIdGoods"></Cascader>
|
||||
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="范围描述" prop="description">
|
||||
<Input
|
||||
v-model="form.description"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
maxlength="50"
|
||||
show-word-limit
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<div>
|
||||
<Button type="text" @click="$router.push({ name: 'coupon' })"
|
||||
>返回</Button
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
:loading="submitLoading"
|
||||
@click="handleSubmit"
|
||||
>提交</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</Card>
|
||||
<sku-select
|
||||
ref="skuSelect"
|
||||
@selectedGoodsData="selectedGoodsData"
|
||||
></sku-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { saveShopCoupon, getShopCoupon, editShopCoupon } from "@/api/promotion";
|
||||
import { getGoodsCategoryAll } from "@/api/goods";
|
||||
import { regular } from "@/utils";
|
||||
import skuSelect from "@/views/lili-dialog";
|
||||
export default {
|
||||
name: "addCoupon",
|
||||
components: {
|
||||
skuSelect,
|
||||
},
|
||||
data() {
|
||||
const checkPrice = (rule, value, callback) => {
|
||||
if (!value && value !== 0) {
|
||||
return callback(new Error("面额不能为空"));
|
||||
} else if (!regular.money.test(value)) {
|
||||
callback(new Error("请输入正整数或者两位小数"));
|
||||
} else if (parseFloat(value) > 99999999) {
|
||||
callback(new Error("面额设置超过上限值"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const checkWeight = (rule, value, callback) => {
|
||||
if (!value && typeof value !== "number") {
|
||||
callback(new Error("消费门槛不能为空"));
|
||||
} else if (!regular.money.test(value)) {
|
||||
callback(new Error("请输入正整数或者两位小数"));
|
||||
} else if (parseFloat(value) > 99999999) {
|
||||
callback(new Error("消费门槛设置超过上限值"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const isLtEndDate = (rule, value, callback) => {
|
||||
if (new Date(value).getTime() > new Date(this.form.endTime).getTime()) {
|
||||
callback(new Error());
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const isGtStartDate = (rule, value, callback) => {
|
||||
if (new Date(value).getTime() < new Date(this.form.startTime).getTime()) {
|
||||
callback(new Error());
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
modalType: 0, // 判断是新增还是编辑优惠券 0 新增 1 编辑
|
||||
categoryId: 0, // 分类id
|
||||
form: {
|
||||
/** 店铺承担比例 */
|
||||
sellerCommission: 0,
|
||||
/** 发行数量 */
|
||||
publishNum: 1,
|
||||
/** 运费承担者 */
|
||||
scopeType: "ALL",
|
||||
/** 限领数量 */
|
||||
couponLimitNum: 1,
|
||||
/** 活动类型 */
|
||||
couponType: "PRICE",
|
||||
/** 优惠券名称 */
|
||||
couponName: "",
|
||||
getType: "FREE",
|
||||
promotionGoodsList: [],
|
||||
scopeIdGoods: [],
|
||||
},
|
||||
id: this.$route.query.id,
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectedGoods: [], // 已选商品列表,便于删除
|
||||
goodsCategoryList: [], // 商品分类列表
|
||||
shopCategoryList: [], // 店铺分类列表
|
||||
cascaderProps: {
|
||||
multiple: true,
|
||||
label: "name",
|
||||
value: "id",
|
||||
}, // 级联选择器配置项
|
||||
formRule: {
|
||||
promotionName: [{ required: true, message: "活动名称不能为空" }],
|
||||
couponName: [{ required: true, message: "优惠券名称不能为空" }],
|
||||
couponLimitNum: [{ required: true, message: "领取限制不能为空" }],
|
||||
price: [
|
||||
{ required: true, message: "请输入面额" },
|
||||
{ validator: checkPrice },
|
||||
],
|
||||
consumeThreshold: [
|
||||
{ required: true, message: "请输入消费门槛" },
|
||||
{ validator: checkWeight },
|
||||
],
|
||||
startTime: [
|
||||
{
|
||||
required: true,
|
||||
type: "date",
|
||||
message: "请选择开始时间",
|
||||
},
|
||||
{
|
||||
trigger: "change",
|
||||
message: "开始时间要小于结束时间",
|
||||
validator: isLtEndDate,
|
||||
},
|
||||
],
|
||||
endTime: [
|
||||
{
|
||||
required: true,
|
||||
type: "date",
|
||||
message: "请选择结束时间",
|
||||
},
|
||||
{
|
||||
trigger: "change",
|
||||
message: "结束时间要大于开始时间",
|
||||
validator: isGtStartDate,
|
||||
},
|
||||
],
|
||||
couponDiscount: [
|
||||
{ required: true, message: "请输入折扣" },
|
||||
{
|
||||
pattern: regular.discount,
|
||||
message: "请输入0-10的数字,可有一位小数",
|
||||
},
|
||||
],
|
||||
sellerCommission: [
|
||||
{ required: true, message: "请输入店铺承担比例" },
|
||||
{ pattern: regular.rate, message: "请输入0-100的正整数" },
|
||||
],
|
||||
publishNum: [
|
||||
{ required: true, message: "请输入发放数量" },
|
||||
{ pattern: regular.integer, message: "请输入正整数" },
|
||||
],
|
||||
couponLimitNum: [
|
||||
{ required: true, message: "请输入领取限制" },
|
||||
{ pattern: regular.integer, message: "请输入正整数" },
|
||||
],
|
||||
description: [{ required: true, message: "请输入范围描述" }],
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
type: "selection",
|
||||
width: 60,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "商品价格",
|
||||
key: "price",
|
||||
minWidth: 40,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.price, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "库存",
|
||||
key: "quantity",
|
||||
minWidth: 40,
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
minWidth: 50,
|
||||
align: "center",
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
size: "small",
|
||||
type: "error",
|
||||
ghost: true,
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.delGoods(params.index);
|
||||
},
|
||||
},
|
||||
},
|
||||
"删除"
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
options: {
|
||||
disabledDate(date) {
|
||||
return date && date.valueOf() < Date.now() - 86400000;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
await this.getCagetoryList();
|
||||
// 如果id不为空则查询信息
|
||||
if (this.id) {
|
||||
this.getCoupon();
|
||||
this.modalType = 1;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCoupon() {
|
||||
getShopCoupon(this.id).then((res) => {
|
||||
let data = res.result;
|
||||
if (!data.promotionGoodsList) data.promotionGoodsList = [];
|
||||
if (data.scopeType == "PORTION_GOODS_CATEGORY") {
|
||||
let prevCascader = data.scopeId.split(",");
|
||||
function next(params, prev) {
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
const item = params[i];
|
||||
if (item.children) {
|
||||
next(item.children, [...prev, item]);
|
||||
} else {
|
||||
if (prevCascader.includes(item.id)) {
|
||||
prevCascader = prevCascader.map((key) => {
|
||||
if (key === item.id) {
|
||||
let result = prev.map((item) => item.id);
|
||||
return [...result, item.id];
|
||||
} else {
|
||||
return key;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
i === params.length - 1 && (prev = []);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next(this.goodsCategoryList, []);
|
||||
data.scopeIdGoods = prevCascader;
|
||||
}
|
||||
this.form = data;
|
||||
});
|
||||
},
|
||||
/** 保存平台优惠券 */
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
const params = JSON.parse(JSON.stringify(this.form));
|
||||
const strat = this.$options.filters.unixToDate(
|
||||
this.form.startTime / 1000
|
||||
);
|
||||
const end = this.$options.filters.unixToDate(
|
||||
this.form.endTime / 1000
|
||||
);
|
||||
let scopeId = [];
|
||||
params.startTime = strat;
|
||||
params.endTime = end;
|
||||
|
||||
if (
|
||||
params.scopeType == "PORTION_GOODS" &&
|
||||
(!params.promotionGoodsList ||
|
||||
params.promotionGoodsList.length == 0)
|
||||
) {
|
||||
this.$Modal.warning({ title: "提示", content: "请选择指定商品" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
params.scopeType == "PORTION_GOODS_CATEGORY" &&
|
||||
(!params.scopeIdGoods || params.scopeIdGoods.length == 0)
|
||||
) {
|
||||
this.$Modal.warning({ title: "提示", content: "请选择商品分类" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (params.scopeType == "PORTION_GOODS") {
|
||||
//指定商品
|
||||
params.promotionGoodsList.forEach((item) => {
|
||||
scopeId.push(item.skuId);
|
||||
});
|
||||
params.scopeId = scopeId.toString();
|
||||
} else if (params.scopeType == "ALL") {
|
||||
delete params.promotionGoodsList;
|
||||
} else if (params.scopeType == "PORTION_GOODS_CATEGORY") {
|
||||
//部分商品分类
|
||||
scopeId = this.filterCategoryId(params.scopeIdGoods, []);
|
||||
params.scopeId = scopeId.toString();
|
||||
delete params.promotionGoodsList;
|
||||
}
|
||||
delete params.scopeIdGoods;
|
||||
|
||||
this.submitLoading = true;
|
||||
if (this.modalType === 0) {
|
||||
// 添加 避免编辑后传入id等数据 记得删除
|
||||
delete params.id;
|
||||
saveShopCoupon(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("优惠券发送成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 编辑
|
||||
delete params.consumeLimit;
|
||||
delete params.couponDiscount;
|
||||
delete params.updateTime;
|
||||
|
||||
editShopCoupon(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("优惠券修改成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 关闭当前页面
|
||||
closeCurrentPage() {
|
||||
this.$store.commit("removeTag", "add-coupon");
|
||||
localStorage.storeOpenedList = JSON.stringify(
|
||||
this.$store.state.app.storeOpenedList
|
||||
);
|
||||
this.$router.push({
|
||||
path: "promotion/coupon",
|
||||
});
|
||||
},
|
||||
changeSelect(e) {
|
||||
// 已选商品批量选择
|
||||
this.selectedGoods = e;
|
||||
},
|
||||
delSelectGoods() {
|
||||
// 多选删除商品
|
||||
if (this.selectedGoods.length <= 0) {
|
||||
this.$Message.warning("您还未选择要删除的数据");
|
||||
return;
|
||||
}
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除所选商品吗?",
|
||||
onOk: () => {
|
||||
let ids = [];
|
||||
this.selectedGoods.forEach(function (e) {
|
||||
ids.push(e.id);
|
||||
});
|
||||
this.form.promotionGoodsList = this.form.promotionGoodsList.filter(
|
||||
(item) => {
|
||||
return !ids.includes(item.id);
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
},
|
||||
delGoods(index) {
|
||||
// 删除商品
|
||||
this.form.promotionGoodsList.splice(index, 1);
|
||||
},
|
||||
selectedGoodsData(item) {
|
||||
// 回显已选商品
|
||||
let ids = [];
|
||||
let list = [];
|
||||
this.form.promotionGoodsList.forEach((e) => {
|
||||
ids.push(e.id);
|
||||
});
|
||||
item.forEach((e) => {
|
||||
if (!ids.includes(e.id)) {
|
||||
list.push({
|
||||
goodsName: e.goodsName,
|
||||
price: e.price,
|
||||
originalPrice: e.price,
|
||||
quantity: e.quantity,
|
||||
storeId: e.storeId,
|
||||
sellerName: e.sellerName,
|
||||
skuId: e.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.form.promotionGoodsList.push(...list);
|
||||
},
|
||||
getGoodsCategory(e) {
|
||||
// 获取级联选择器商品分类id
|
||||
},
|
||||
|
||||
async getCagetoryList() {
|
||||
// 获取全部商品分类
|
||||
let data = await getGoodsCategoryAll();
|
||||
this.goodsCategoryList = this.filterCategory(data.result);
|
||||
// 过滤出可显示的值
|
||||
|
||||
this.goodsCategoryList = this.goodsCategoryList.map((item) => {
|
||||
if (item.children) {
|
||||
item.children = item.children.map((child) => {
|
||||
if (child.children) {
|
||||
child.children = child.children.map((son) => {
|
||||
return {
|
||||
value: son.id,
|
||||
label: son.name,
|
||||
};
|
||||
});
|
||||
return {
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
children: child.children,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
return { value: item.id, label: item.name, children: item.children };
|
||||
});
|
||||
},
|
||||
filterCategory(list) {
|
||||
// 递归删除空children
|
||||
list.forEach((item) => {
|
||||
if (item.children.length == 0) {
|
||||
delete item.children;
|
||||
} else {
|
||||
this.filterCategory(item.children);
|
||||
}
|
||||
});
|
||||
return list;
|
||||
},
|
||||
filterCategoryId(list, idArr) {
|
||||
// 递归获取分类id
|
||||
list.forEach((e) => {
|
||||
if (e instanceof Array) {
|
||||
this.filterCategoryId(e, idArr);
|
||||
} else {
|
||||
if (!idArr.includes(e)) idArr.push(e);
|
||||
}
|
||||
});
|
||||
return idArr;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scpoed>
|
||||
h4 {
|
||||
margin-bottom: 10px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #f8f8f8;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
text-align: left;
|
||||
}
|
||||
.describe {
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
}
|
||||
.ivu-form-item{
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
.wrapper{
|
||||
min-height: 1000px;
|
||||
}
|
||||
</style>
|
||||
|
||||
267
seller/src/views/promotion/fullCut/full-cut.vue
Normal file
267
seller/src/views/promotion/fullCut/full-cut.vue
Normal file
@@ -0,0 +1,267 @@
|
||||
<template>
|
||||
<div class="full-cut">
|
||||
<Card>
|
||||
<Row>
|
||||
<Form
|
||||
ref="searchForm"
|
||||
:model="searchForm"
|
||||
inline
|
||||
:label-width="70"
|
||||
class="search-form"
|
||||
>
|
||||
<Form-item label="活动名称">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.promotionName"
|
||||
placeholder="请输入活动名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="活动状态" prop="promotionStatus">
|
||||
<Select
|
||||
v-model="searchForm.promotionStatus"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<Option value="NEW">未开始</Option>
|
||||
<Option value="START">已开始/上架</Option>
|
||||
<Option value="END">已结束/下架</Option>
|
||||
<Option value="CLOSE">紧急关闭/作废</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="活动时间">
|
||||
<DatePicker
|
||||
v-model="selectDate"
|
||||
type="daterange"
|
||||
clearable
|
||||
placeholder="选择起始时间"
|
||||
style="width: 200px"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Button @click="handleSearch" type="primary" class="search-btn" icon="ios-search">搜索</Button>
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="operation">
|
||||
<Button type="primary" @click="newAct">新增</Button>
|
||||
</Row>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="{ row }" slot="applyEndTime">
|
||||
{{ unixDate(row.applyEndTime) }}
|
||||
</template>
|
||||
<template slot-scope="{ row }" slot="promotionType">
|
||||
{{ row.isFullMinus ? "满减" : "满折" }}
|
||||
</template>
|
||||
<template slot-scope="{ row }" slot="hours">
|
||||
<Tag v-for="item in unixHours(row.hours)" :key="item">{{
|
||||
item
|
||||
}}</Tag>
|
||||
</template>
|
||||
<template slot-scope="{ row }" slot="action">
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
v-if="row.promotionStatus == 'NEW'"
|
||||
size="small"
|
||||
@click="edit(row)"
|
||||
>编辑</Button
|
||||
>
|
||||
<Button type="success" v-else size="small" @click="edit(row)"
|
||||
>查看</Button
|
||||
>
|
||||
<Button
|
||||
type="error"
|
||||
:disabled="row.promotionStatus == 'START'"
|
||||
ghost
|
||||
size="small"
|
||||
@click="del(row)"
|
||||
>删除</Button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page operation">
|
||||
<Page
|
||||
:current="searchForm.pageNumber + 1"
|
||||
: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 { getFullDiscountList, delFullDiscount } from "@/api/promotion.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false, // 表单加载状态
|
||||
searchForm: { // 列表请求参数
|
||||
pageNumber: 0,
|
||||
pageSize: 10,
|
||||
sort: "startTime",
|
||||
order: "desc",
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
title: "活动名称",
|
||||
key: "promotionName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "开始时间",
|
||||
key: "startTime",
|
||||
minWidth: 60,
|
||||
},
|
||||
{
|
||||
title: "结束时间",
|
||||
key: "endTime",
|
||||
minWidth: 60,
|
||||
},
|
||||
{
|
||||
title: "活动类型",
|
||||
slot: "promotionType",
|
||||
minWidth: 60,
|
||||
},
|
||||
{
|
||||
title: "活动状态",
|
||||
key: "promotionStatus",
|
||||
minWidth: 60,
|
||||
render: (h, params) => {
|
||||
let text = "未知",
|
||||
color = "default";
|
||||
if (params.row.promotionStatus == "NEW") {
|
||||
text = "未开始";
|
||||
color = "default";
|
||||
} else if (params.row.promotionStatus == "START") {
|
||||
text = "已开始";
|
||||
color = "green";
|
||||
} else if (params.row.promotionStatus == "END") {
|
||||
text = "已结束";
|
||||
color = "blue";
|
||||
} else if (params.row.promotionStatus == "CLOSE") {
|
||||
text = "已关闭";
|
||||
color = "red";
|
||||
}
|
||||
return h("div", [
|
||||
h(
|
||||
"Tag",
|
||||
{
|
||||
props: {
|
||||
color: color,
|
||||
},
|
||||
},
|
||||
text
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
slot: "action",
|
||||
align: "center",
|
||||
width: 200,
|
||||
},
|
||||
],
|
||||
data: [], // 表格数据
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
newAct() {
|
||||
// 新增活动
|
||||
this.$router.push({ name: "full-cut-detail" });
|
||||
},
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
// 改变页数
|
||||
this.searchForm.pageNumber = v - 1;
|
||||
this.getDataList();
|
||||
},
|
||||
changePageSize(v) {
|
||||
// 改变页码
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
// 搜索
|
||||
this.searchForm.pageNumber = 0;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
edit(row) {
|
||||
// 编辑
|
||||
this.$router.push({ name: "full-cut-detail", query: { id: row.id } });
|
||||
},
|
||||
del(row) {
|
||||
this.$Modal.confirm({
|
||||
title: "提示",
|
||||
// 记得确认修改此处
|
||||
content: "确认删除此活动吗?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
// 删除
|
||||
delFullDiscount(row.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
|
||||
this.searchForm.startTime = this.selectDate[0].getTime();
|
||||
this.searchForm.endTime = this.selectDate[1].getTime();
|
||||
} else {
|
||||
this.searchForm.startTime = null;
|
||||
this.searchForm.endTime = null;
|
||||
}
|
||||
getFullDiscountList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
watch: {
|
||||
$route(to, from) {
|
||||
if (to.fullPath == "/promotion/full-cut") {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.operation {
|
||||
margin: 10px 0;
|
||||
}
|
||||
</style>
|
||||
576
seller/src/views/promotion/fullCut/newFullCut.vue
Normal file
576
seller/src/views/promotion/fullCut/newFullCut.vue
Normal file
@@ -0,0 +1,576 @@
|
||||
<template>
|
||||
<div>
|
||||
<Card>
|
||||
<Form ref="form" :model="form" :label-width="120" :rules="formRule">
|
||||
<div class="base-info-item">
|
||||
<h4>基本信息</h4>
|
||||
<div class="form-item-view">
|
||||
<FormItem label="活动名称" prop="promotionName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="form.promotionName"
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
placeholder="活动名称"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="活动时间" prop="rangeTime">
|
||||
<DatePicker
|
||||
type="datetimerange"
|
||||
v-model="form.rangeTime"
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择"
|
||||
:options="options"
|
||||
style="width: 320px"
|
||||
>
|
||||
</DatePicker>
|
||||
</FormItem>
|
||||
<FormItem label="活动描述" prop="description">
|
||||
<Input
|
||||
v-model="form.description"
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<h4>优惠设置</h4>
|
||||
<div class="form-item-view">
|
||||
<FormItem label="优惠门槛" prop="fullMoney">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="form.fullMoney"
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
placeholder="优惠门槛"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
<span class="describe">消费达到当前金额可以参与优惠</span>
|
||||
</FormItem>
|
||||
<FormItem label="优惠方式">
|
||||
<RadioGroup v-model="form.discountType">
|
||||
<Radio
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
label="isFullMinus"
|
||||
>减现金</Radio
|
||||
>
|
||||
<Radio
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
label="isFullRate"
|
||||
>打折</Radio
|
||||
>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="form.discountType == 'isFullMinus'"
|
||||
label="优惠金额"
|
||||
prop="fullMinus"
|
||||
>
|
||||
<Input
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
type="text"
|
||||
v-model="form.fullMinus"
|
||||
placeholder="优惠金额"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="form.discountType == 'isFullRate'"
|
||||
label="优惠折扣"
|
||||
prop="fullRate"
|
||||
>
|
||||
<Input
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
type="text"
|
||||
v-model="form.fullRate"
|
||||
placeholder="优惠折扣"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
<span class="describe">优惠折扣为0-10之间数字,可有一位小数</span>
|
||||
</FormItem>
|
||||
<FormItem label="额外赠送">
|
||||
<Checkbox
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
v-model="form.isFreeFreight"
|
||||
>免邮费</Checkbox
|
||||
>
|
||||
<Checkbox
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
v-model="form.isCoupon"
|
||||
>送优惠券</Checkbox
|
||||
>
|
||||
<Checkbox
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
v-model="form.isGift"
|
||||
>送赠品</Checkbox
|
||||
>
|
||||
<Checkbox
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
v-model="form.isPoint"
|
||||
>送积分</Checkbox
|
||||
>
|
||||
</FormItem>
|
||||
<FormItem v-if="form.isCoupon" label="赠送优惠券" prop="couponId">
|
||||
<Select
|
||||
v-model="form.couponId"
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
filterable
|
||||
:remote-method="getCouponList"
|
||||
placeholder="输入优惠券名称搜索"
|
||||
:loading="couponLoading"
|
||||
style="width: 260px"
|
||||
>
|
||||
<Option
|
||||
v-for="item in couponList"
|
||||
:value="item.id"
|
||||
:key="item.id"
|
||||
>{{ item.couponName }}</Option
|
||||
>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem v-if="form.isGift" label="赠品" prop="giftId">
|
||||
<Select
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
v-model="form.giftId"
|
||||
filterable
|
||||
:remote-method="getGiftList"
|
||||
placeholder="输入赠品名称搜索"
|
||||
:loading="giftLoading"
|
||||
style="width: 260px"
|
||||
>
|
||||
<Option
|
||||
v-for="item in giftList"
|
||||
:value="item.id"
|
||||
:key="item.id"
|
||||
>{{ item.goodsName }}</Option
|
||||
>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem v-if="form.isPoint" label="赠积分" prop="point">
|
||||
<Input
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
v-model="form.point"
|
||||
type="number"
|
||||
:min="0"
|
||||
style="width: 260px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="使用范围" prop="scopeType">
|
||||
<RadioGroup v-model="form.scopeType">
|
||||
<Radio :disabled="form.promotionStatus != 'NEW'" label="ALL"
|
||||
>全品类</Radio
|
||||
>
|
||||
<Radio
|
||||
:disabled="form.promotionStatus != 'NEW'"
|
||||
label="PORTION_GOODS"
|
||||
>指定商品</Radio
|
||||
>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
style="width: 100%"
|
||||
v-if="form.scopeType == 'PORTION_GOODS'"
|
||||
>
|
||||
<div
|
||||
style="display: flex; margin-bottom: 10px"
|
||||
v-if="form.promotionStatus == 'NEW'"
|
||||
>
|
||||
<Button type="primary" @click="$refs.skuSelect.open('goods')"
|
||||
>选择商品</Button
|
||||
>
|
||||
<Button
|
||||
type="error"
|
||||
ghost
|
||||
style="margin-left: 10px"
|
||||
@click="delSelectGoods"
|
||||
>批量删除</Button
|
||||
>
|
||||
</div>
|
||||
<Table
|
||||
border
|
||||
:columns="columns"
|
||||
:data="form.promotionGoodsList"
|
||||
@on-selection-change="changeSelect"
|
||||
>
|
||||
<template slot-scope="{ row }" slot="QRCode">
|
||||
<img
|
||||
:src="row.QRCode || '../../../assets/lili.png'"
|
||||
width="50px"
|
||||
height="50px"
|
||||
alt=""
|
||||
/>
|
||||
</template>
|
||||
<template slot-scope="{ index }" slot="action">
|
||||
<Button
|
||||
type="error"
|
||||
:disabled="form.promotionStatus != 'NEW' && id"
|
||||
size="small"
|
||||
ghost
|
||||
@click="delGoods(index)"
|
||||
>删除</Button
|
||||
>
|
||||
</template>
|
||||
</Table>
|
||||
</FormItem>
|
||||
|
||||
<div>
|
||||
<Button type="text" @click="closeCurrentPage"
|
||||
>返回</Button
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
:disabled="form.promotionStatus != 'NEW' && id"
|
||||
:loading="submitLoading"
|
||||
@click="handleSubmit"
|
||||
>提交</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</Card>
|
||||
<sku-select
|
||||
ref="skuSelect"
|
||||
@selectedGoodsData="selectedGoodsData"
|
||||
></sku-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getShopCouponList,
|
||||
getFullDiscountById,
|
||||
newFullDiscount,
|
||||
editFullDiscount,
|
||||
} from "@/api/promotion";
|
||||
import { getGoodsSkuListDataSeller } from "@/api/goods";
|
||||
import { regular } from "@/utils";
|
||||
import skuSelect from "@/views/lili-dialog";
|
||||
export default {
|
||||
name: "addFullCut",
|
||||
components: {
|
||||
skuSelect,
|
||||
},
|
||||
data() {
|
||||
const checkPrice = (rule, value, callback) => {
|
||||
if (!value && value !== 0) {
|
||||
return callback(new Error("面额不能为空"));
|
||||
} else if (!regular.money.test(value)) {
|
||||
callback(new Error("请输入正整数或者两位小数"));
|
||||
} else if (parseFloat(value) > 99999999) {
|
||||
callback(new Error("面额设置超过上限值"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const checkWeight = (rule, value, callback) => {
|
||||
if (!value && typeof value !== "number") {
|
||||
callback(new Error("优惠门槛不能为空"));
|
||||
} else if (!regular.money.test(value)) {
|
||||
callback(new Error("请输入正整数或者两位小数"));
|
||||
} else if (parseFloat(value) > 99999999) {
|
||||
callback(new Error("优惠门槛设置超过上限值"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
form: { // 活动表单
|
||||
discountType: "isFullMinus",
|
||||
scopeType: "ALL",
|
||||
promotionGoodsList: [],
|
||||
promotionStatus: "NEW",
|
||||
},
|
||||
id: this.$route.query.id, // 活动id
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectedGoods: [], // 已选商品列表,便于删除
|
||||
formRule: { // 验证规则
|
||||
promotionName: [{ required: true, message: "活动名称不能为空" }],
|
||||
rangeTime: [{ required: true, message: "请选择活动时间" }],
|
||||
description: [{ required: true, message: "请填写活动描述" }],
|
||||
price: [
|
||||
{ required: true, message: "请输入面额" },
|
||||
{ validator: checkPrice },
|
||||
],
|
||||
consumptionLimit: [{ required: true, validator: checkWeight }],
|
||||
fullMoney: [{ required: true, validator: checkWeight }],
|
||||
fullMinus: [
|
||||
{ required: true, message: "请填写优惠金额" },
|
||||
{ pattern: regular.money, message: "请输入正确金额" },
|
||||
],
|
||||
fullRate: [
|
||||
{ required: true, message: "请填写优惠折扣" },
|
||||
{
|
||||
pattern: regular.discount,
|
||||
message: "请输入0-10的数字,可有一位小数",
|
||||
},
|
||||
],
|
||||
couponId: [{ required: true, message: "请选择优惠券" }],
|
||||
giftId: [{ required: true, message: "请选择赠品" }],
|
||||
point: [{ required: true, message: "请填写积分" }],
|
||||
},
|
||||
couponList: [], // 店铺优惠券列表
|
||||
giftList: [], // 赠品列表
|
||||
giftLoading: false, // 请求赠品状态
|
||||
columns: [ // 表头
|
||||
{
|
||||
type: "selection",
|
||||
width: 60,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "商品价格",
|
||||
key: "price",
|
||||
minWidth: 40,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.price, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "库存",
|
||||
key: "quantity",
|
||||
minWidth: 40,
|
||||
},
|
||||
{
|
||||
title: "商品二维码",
|
||||
slot: "QRCode",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
slot: "action",
|
||||
minWidth: 50,
|
||||
},
|
||||
],
|
||||
options: {
|
||||
disabledDate(date) {
|
||||
return date && date.valueOf() < Date.now() - 86400000;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
if (this.id) {
|
||||
this.getDetail();
|
||||
}
|
||||
this.getCouponList();
|
||||
this.getGiftList();
|
||||
},
|
||||
methods: {
|
||||
// 关闭当前页面
|
||||
closeCurrentPage() {
|
||||
this.$store.commit("removeTag", "full-cut-detail");
|
||||
localStorage.storeOpenedList = JSON.stringify(
|
||||
this.$store.state.app.storeOpenedList
|
||||
);
|
||||
this.$router.go(-1);
|
||||
},
|
||||
getDetail() {
|
||||
// 获取活动详情
|
||||
getFullDiscountById(this.id).then((res) => {
|
||||
let data = res.result;
|
||||
if (data.number == -1) {
|
||||
data.promotionGoodsList = [];
|
||||
data.scopeType = "ALL";
|
||||
} else {
|
||||
data.scopeType = "PORTION_GOODS";
|
||||
}
|
||||
if (data.isFullMinus) {
|
||||
data.discountType = "isFullMinus";
|
||||
delete data.isFullMinus;
|
||||
} else {
|
||||
data.discountType = "isFullMinus";
|
||||
delete data.isFullRate;
|
||||
}
|
||||
data.rangeTime = [];
|
||||
data.rangeTime.push(new Date(data.startTime), new Date(data.endTime));
|
||||
|
||||
this.form = data;
|
||||
});
|
||||
},
|
||||
/** 保存 */
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
const params = JSON.parse(JSON.stringify(this.form));
|
||||
const strat = this.$options.filters.unixToDate(
|
||||
this.form.rangeTime[0] / 1000
|
||||
);
|
||||
const end = this.$options.filters.unixToDate(
|
||||
this.form.rangeTime[1] / 1000
|
||||
);
|
||||
params.startTime = strat;
|
||||
params.endTime = end;
|
||||
|
||||
if (
|
||||
params.scopeType == "PORTION_GOODS" &&
|
||||
(!params.promotionGoodsList ||
|
||||
params.promotionGoodsList.length == 0)
|
||||
) {
|
||||
this.$Modal.warning({ title: "提示", content: "请选择指定商品" });
|
||||
return;
|
||||
}
|
||||
if (params.scopeType == "ALL") {
|
||||
delete params.promotionGoodsList;
|
||||
params.number = -1;
|
||||
} else {
|
||||
params.number = 1;
|
||||
params.promotionGoodsList.forEach((e) => {
|
||||
e.startTime = params.stratTime;
|
||||
e.endTime = params.endTime;
|
||||
});
|
||||
}
|
||||
if (params.discountType == "isFullMinus") {
|
||||
params.isFullMinus = true;
|
||||
} else {
|
||||
params.isFullRate = true;
|
||||
}
|
||||
delete params.scopeType;
|
||||
delete params.rangeTime;
|
||||
this.submitLoading = true;
|
||||
if (!this.id) {
|
||||
// 添加 避免编辑后传入id等数据 记得删除
|
||||
delete params.id;
|
||||
newFullDiscount(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("添加活动成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 编辑
|
||||
delete params.updateTime;
|
||||
|
||||
editFullDiscount(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("编辑活动成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
changeSelect(e) {
|
||||
// 已选商品批量选择
|
||||
this.selectedGoods = e;
|
||||
},
|
||||
delSelectGoods() {
|
||||
// 多选删除商品
|
||||
if (this.selectedGoods.length <= 0) {
|
||||
this.$Message.warning("您还未选择要删除的数据");
|
||||
return;
|
||||
}
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除所选商品吗?",
|
||||
onOk: () => {
|
||||
let ids = [];
|
||||
this.selectedGoods.forEach(function (e) {
|
||||
ids.push(e.id);
|
||||
});
|
||||
this.form.promotionGoodsList = this.form.promotionGoodsList.filter(
|
||||
(item) => {
|
||||
return !ids.includes(item.id);
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
},
|
||||
delGoods(index) {
|
||||
// 删除商品
|
||||
this.form.promotionGoodsList.splice(index, 1);
|
||||
},
|
||||
selectedGoodsData(item) {
|
||||
// 回显已选商品
|
||||
let ids = [];
|
||||
let list = [];
|
||||
this.form.promotionGoodsList.forEach((e) => {
|
||||
ids.push(e.id);
|
||||
});
|
||||
item.forEach((e) => {
|
||||
if (!ids.includes(e.id)) {
|
||||
list.push({
|
||||
goodsName: e.goodsName,
|
||||
price: e.price,
|
||||
quantity: e.quantity,
|
||||
storeId: e.storeId,
|
||||
sellerName: e.sellerName,
|
||||
skuId: e.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.form.promotionGoodsList.push(...list);
|
||||
},
|
||||
getCouponList(query) {
|
||||
// 优惠券列表
|
||||
let params = {
|
||||
pageSize: 10,
|
||||
pageNumber: 0,
|
||||
getType: "ACTIVITY",
|
||||
couponName: query,
|
||||
};
|
||||
this.couponLoading = true;
|
||||
getShopCouponList(params).then((res) => {
|
||||
this.couponLoading = false;
|
||||
if (res.success) {
|
||||
this.couponList = res.result.records;
|
||||
}
|
||||
});
|
||||
},
|
||||
getGiftList(query) {
|
||||
// 赠品列表
|
||||
let params = {
|
||||
pageSize: 10,
|
||||
pageNumber: 1,
|
||||
goodsName: query,
|
||||
};
|
||||
this.giftLoading = true;
|
||||
getGoodsSkuListDataSeller(params).then((res) => {
|
||||
this.giftLoading = false;
|
||||
if (res.success) {
|
||||
this.giftList = res.result.records;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
h4 {
|
||||
margin-bottom: 10px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #f8f8f8;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
text-align: left;
|
||||
}
|
||||
.describe {
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
||||
232
seller/src/views/promotion/pintuan/newPintuan.vue
Normal file
232
seller/src/views/promotion/pintuan/newPintuan.vue
Normal file
@@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<div class="new-pintuan">
|
||||
<Card>
|
||||
<Form ref="form" :model="form" :label-width="130" :rules="formValidate">
|
||||
<FormItem label="活动名称" prop="promotionName" :label-width="130">
|
||||
<Input v-model="form.promotionName" clearable style="width: 260px" />
|
||||
<div style="color: #cccccc">
|
||||
活动名称将显示在对人拼团活动列表中,方便商家管理使用,最多输入25个字符
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="活动时间" prop="startTime">
|
||||
<DatePicker
|
||||
type="datetime"
|
||||
v-model="form.startTime"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
:options="options"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
</DatePicker>
|
||||
-
|
||||
<DatePicker
|
||||
type="datetime"
|
||||
v-model="form.endTime"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
:options="options"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
</DatePicker>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="参团人数" prop="requiredNum" :label-width="130">
|
||||
<Input v-model="form.requiredNum" style="width: 260px">
|
||||
<span slot="append">人</span>
|
||||
</Input>
|
||||
<span style="color: #cccccc"
|
||||
>建议参团人数不少于2人,不超过20人。</span
|
||||
>
|
||||
</FormItem>
|
||||
<FormItem label="限购数量" prop="limitNum" :label-width="130">
|
||||
<Input v-model="form.limitNum" type="number" style="width: 260px">
|
||||
<span slot="append">件/人</span>
|
||||
</Input>
|
||||
<span style="color: #cccccc">如果设置为0则视为不限制购买数量</span>
|
||||
</FormItem>
|
||||
<FormItem label="虚拟成团" prop="fictitious">
|
||||
<RadioGroup v-model="form.fictitious">
|
||||
<Radio title="开启" :label="true">
|
||||
<span>开启</span>
|
||||
</Radio>
|
||||
<Radio title="关闭" :label="false">
|
||||
<span>关闭</span>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
<br />
|
||||
<span style="color: #cccccc"
|
||||
>开启虚拟成团后,24小时人数未满的团,系统将会模拟匿名买家凑满人数,使该团成团;您只需要对已付款参团的真实买家发货;建议合理开启以提高</span
|
||||
>
|
||||
</FormItem>
|
||||
<FormItem label="拼团规则" prop="pintuanRule">
|
||||
<Input
|
||||
v-model="form.pintuanRule"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
<br />
|
||||
<span style="color: #cccccc"
|
||||
>拼团规则描述不能为空且不能大于255个字,会在WAP拼团详情页面显示</span
|
||||
>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div>
|
||||
<Button type="text" @click="closeCurrentPage">返回</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
|
||||
>提交</Button
|
||||
>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { savePintuan, editPintuan, getPintuanDetail } from "@/api/promotion";
|
||||
export default {
|
||||
data() {
|
||||
const isLtEndDate = (rule, value, callback) => {
|
||||
if (new Date(value).getTime() > new Date(this.form.endTime).getTime()) {
|
||||
callback(new Error());
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const isGtStartDate = (rule, value, callback) => {
|
||||
if (new Date(value).getTime() < new Date(this.form.startTime).getTime()) {
|
||||
callback(new Error());
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
id: this.$route.query.id, // 拼团id
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
promotionName: "",
|
||||
promotionTitle: "",
|
||||
pintuanRule: "",
|
||||
requiredNum: "",
|
||||
fictitious: false,
|
||||
limitNum: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {
|
||||
promotionName: [{ required: true, message: "活动名称不能为空" }],
|
||||
requiredNum: [
|
||||
{ required: true, message: "参团人数不能为空" },
|
||||
{
|
||||
pattern: /^(1|[1-9]\d?|100)$/,
|
||||
message: "参团人数不合法",
|
||||
},
|
||||
],
|
||||
limitNum: [
|
||||
{ required: true, message: "限购数不能为空" },
|
||||
{
|
||||
pattern: /^(0|[1-9]\d?|100)$/,
|
||||
message: "限购数不合法",
|
||||
},
|
||||
],
|
||||
startTime: [
|
||||
{
|
||||
required: true,
|
||||
type: "date",
|
||||
message: "请选择开始时间",
|
||||
},
|
||||
{
|
||||
trigger: "change",
|
||||
message: "开始时间要小于结束时间",
|
||||
validator: isLtEndDate,
|
||||
},
|
||||
],
|
||||
endTime: [
|
||||
{
|
||||
required: true,
|
||||
type: "date",
|
||||
message: "请选择结束时间",
|
||||
},
|
||||
{
|
||||
trigger: "change",
|
||||
message: "结束时间要大于开始时间",
|
||||
validator: isGtStartDate,
|
||||
},
|
||||
],
|
||||
},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
options: { // 不可选取的时间段
|
||||
disabledDate(date) {
|
||||
return date && date.valueOf() < Date.now() - 86400000;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
if (this.id) {
|
||||
this.getDetail();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 关闭当前页面
|
||||
closeCurrentPage() {
|
||||
this.$store.commit("removeTag", "new-pintuan");
|
||||
localStorage.storeOpenedList = JSON.stringify(
|
||||
this.$store.state.app.storeOpenedList
|
||||
);
|
||||
this.$router.go(-1);
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
let params = JSON.parse(JSON.stringify(this.form));
|
||||
params.startTime = this.$options.filters.unixToDate(
|
||||
this.form.startTime / 1000
|
||||
);
|
||||
params.endTime = this.$options.filters.unixToDate(
|
||||
this.form.endTime / 1000
|
||||
);
|
||||
if (!this.id) {
|
||||
// 添加 避免编辑后传入id等数据 记得删除
|
||||
delete params.id;
|
||||
savePintuan(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("拼团活动发布成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 编辑
|
||||
if (params.promotionGoodsList == "")
|
||||
delete params.promotionGoodsList;
|
||||
editPintuan(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getDetail() {
|
||||
getPintuanDetail(this.id).then((res) => {
|
||||
if (res.success) {
|
||||
this.form = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/deep/ .ivu-form-item{
|
||||
padding: 18px 10px !important;
|
||||
}
|
||||
</style>
|
||||
41
seller/src/views/promotion/pintuan/pintuan.scss
Normal file
41
seller/src/views/promotion/pintuan/pintuan.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
.search {
|
||||
.operation {
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
.select-clear {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
|
||||
.drop-down {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.newPromotionView {
|
||||
width: 80%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
|
||||
Input {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.slotSpan {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
341
seller/src/views/promotion/pintuan/pintuan.vue
Normal file
341
seller/src/views/promotion/pintuan/pintuan.vue
Normal file
@@ -0,0 +1,341 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
</Col>
|
||||
</Row>
|
||||
<Card>
|
||||
<Row>
|
||||
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
|
||||
<Form-item label="活动名称" prop="promotionName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.promotionName"
|
||||
placeholder="请输入活动名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="活动状态" prop="promotionStatus">
|
||||
<Select
|
||||
v-model="searchForm.promotionStatus"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<Option value="NEW">未开始</Option>
|
||||
<Option value="START">已开始/上架</Option>
|
||||
<Option value="END">已结束/下架</Option>
|
||||
<Option value="CLOSE">紧急关闭/作废</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="活动时间">
|
||||
<DatePicker
|
||||
v-model="selectDate"
|
||||
type="daterange"
|
||||
clearable
|
||||
placeholder="选择起始时间"
|
||||
style="width: 200px"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Button @click="handleSearch" type="primary" class="search-btn " icon="ios-search">搜索</Button>
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="operation padding-row">
|
||||
<Button @click="newAct" type="primary">添加</Button>
|
||||
</Row>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
>
|
||||
<template slot-scope="{ row }" slot="action">
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
v-if="row.promotionStatus == 'NEW'"
|
||||
@click="edit(row)"
|
||||
>编辑</Button
|
||||
>
|
||||
<Button
|
||||
type="info"
|
||||
v-if="row.promotionStatus == 'NEW'"
|
||||
size="small"
|
||||
@click="manage(row)"
|
||||
>管理</Button
|
||||
>
|
||||
<Button
|
||||
type="error"
|
||||
size="small"
|
||||
v-if="row.promotionStatus != 'START'"
|
||||
ghost
|
||||
@click="remove(row)"
|
||||
>删除</Button
|
||||
>
|
||||
<Button
|
||||
type="success"
|
||||
v-if="
|
||||
row.promotionStatus == 'NEW' || row.promotionStatus == 'CLOSE'
|
||||
"
|
||||
size="small"
|
||||
@click="open(row)"
|
||||
>开启</Button
|
||||
>
|
||||
<Button
|
||||
type="warning"
|
||||
v-if="row.promotionStatus == 'START'"
|
||||
size="small"
|
||||
@click="close(row)"
|
||||
>关闭</Button
|
||||
>
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<Page
|
||||
:current="searchForm.pageNumber + 1"
|
||||
: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 {
|
||||
getPintuanList,
|
||||
deletePintuan,
|
||||
openPintuan,
|
||||
closePintuan,
|
||||
} from "@/api/promotion";
|
||||
export default {
|
||||
name: "pintuan",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 0, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "startTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
selectDate: null, // 选择的时间
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
{
|
||||
title: "活动名称",
|
||||
key: "promotionName",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "活动开始时间",
|
||||
key: "startTime",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "活动结束时间",
|
||||
key: "endTime",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "promotionStatus",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
let text = "未知",
|
||||
color = "default";
|
||||
if (params.row.promotionStatus == "NEW") {
|
||||
text = "未开始";
|
||||
color = "default";
|
||||
} else if (params.row.promotionStatus == "START") {
|
||||
text = "已开始";
|
||||
color = "green";
|
||||
} else if (params.row.promotionStatus == "END") {
|
||||
text = "已结束";
|
||||
color = "blue";
|
||||
} else if (params.row.promotionStatus == "CLOSE") {
|
||||
text = "已关闭";
|
||||
color = "red";
|
||||
}
|
||||
return h("div", [h("Tag", { props: { color: color } }, text)]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
slot: "action",
|
||||
align: "center",
|
||||
width: 250,
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v - 1;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 0;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
|
||||
this.searchForm.startTime = this.selectDate[0].getTime();
|
||||
this.searchForm.endTime = this.selectDate[1].getTime();
|
||||
} else {
|
||||
this.searchForm.startTime = null;
|
||||
this.searchForm.endTime = null;
|
||||
}
|
||||
// 带多条件搜索参数获取表单数据 请自行修改接口
|
||||
getPintuanList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
newAct() {
|
||||
this.$router.push({ name: "new-pintuan" });
|
||||
},
|
||||
edit(v) {
|
||||
this.$router.push({ name: "new-pintuan", query: { id: v.id } });
|
||||
},
|
||||
manage(v) {
|
||||
this.$router.push({ name: "pintuan-goods", query: { id: v.id } });
|
||||
},
|
||||
open(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认开启",
|
||||
content: "您确认要开启此拼团活动?",
|
||||
onOk: () => {
|
||||
let params = {
|
||||
startTime: this.openStartTime,
|
||||
endTime: this.openEndTime,
|
||||
};
|
||||
openPintuan(v.id, params).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("开启活动成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
render: (h) => {
|
||||
return h("div", [
|
||||
h("DatePicker", {
|
||||
props: {
|
||||
type: "datetimerange",
|
||||
placeholder: "请选择开始时间和结束时间",
|
||||
},
|
||||
style: {
|
||||
width: "350px",
|
||||
},
|
||||
on: {
|
||||
input: (val) => {
|
||||
if (val[0]) {
|
||||
this.openStartTime = val[0].getTime();
|
||||
}
|
||||
if (val[1]) {
|
||||
this.openEndTime = val[1].getTime();
|
||||
}
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
},
|
||||
});
|
||||
},
|
||||
close(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认关闭",
|
||||
content: "您确认要关闭此拼团活动?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
closePintuan(v.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("关闭活动成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除此拼团活动?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
// 删除
|
||||
deletePintuan(v.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
$route(to, from) {
|
||||
if (to.fullPath == "/promotion/pintuan") {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "pintuan.scss";
|
||||
@import "@/styles/table-common.scss";
|
||||
</style>
|
||||
329
seller/src/views/promotion/pintuan/pintuanGoods.vue
Normal file
329
seller/src/views/promotion/pintuan/pintuanGoods.vue
Normal file
@@ -0,0 +1,329 @@
|
||||
<template>
|
||||
<div class="pintuan-goods">
|
||||
<Card>
|
||||
<Table style="margin: 10px 0" border :columns="columns" :data="data"></Table>
|
||||
|
||||
<Row class="operation">
|
||||
<Button type="primary" @click="openSkuList">选择商品</Button>
|
||||
<Button @click="delAll">批量删除</Button>
|
||||
<Button @click="getDataList" icon="md-refresh">刷新</Button>
|
||||
<Button type="dashed" @click="
|
||||
() => {
|
||||
openTip = !openTip;
|
||||
}
|
||||
">{{ openTip ? "关闭提示" : "开启提示" }}</Button>
|
||||
</Row>
|
||||
<Row v-show="openTip">
|
||||
<Alert show-icon>
|
||||
已选择 <span class="select-count">{{ selectCount }}</span> 项
|
||||
<a class="select-clear" @click="clearSelectAll">清空</a>
|
||||
</Alert>
|
||||
</Row>
|
||||
<Row class="operation">
|
||||
<Table :loading="loading" border :columns="goodsColumns" :data="goodsData" ref="table" sortable="custom" @on-sort-change="changeSort" @on-selection-change="changeSelect">
|
||||
<template slot-scope="{ row, index }" slot="price">
|
||||
<Input v-model="row.price" @input="goodsData[index].price = row.price" />
|
||||
</template>
|
||||
<template slot-scope="{ row }" slot="QRCode">
|
||||
<img :src="row.QRCode || '../../../assets/lili.png'" width="50px" height="50px" alt="" />
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page operation">
|
||||
<Page :current="searchForm.pageNumber + 1" :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>
|
||||
<Row class="operation">
|
||||
<Button @click="closeCurrentPage">返回</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="save">保存</Button>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<sku-select ref="skuSelect" @selectedGoodsData="selectedGoodsData"></sku-select>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getPintuanGoodsList,
|
||||
getPintuanDetail,
|
||||
editPintuan,
|
||||
} from "@/api/promotion.js";
|
||||
import skuSelect from "@/views/lili-dialog";
|
||||
export default {
|
||||
components: {
|
||||
skuSelect,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
openTip: true, // 显示提示
|
||||
loading: false, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 0, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
},
|
||||
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
columns: [
|
||||
{
|
||||
title: "活动名称",
|
||||
key: "promotionName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "活动开始时间",
|
||||
key: "startTime",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "活动结束时间",
|
||||
key: "endTime",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "promotionStatus",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
let text = "未知",
|
||||
color = "";
|
||||
if (params.row.promotionStatus == "NEW") {
|
||||
text = "未开始";
|
||||
color = "default";
|
||||
} else if (params.row.promotionStatus == "START") {
|
||||
text = "已开始";
|
||||
color = "green";
|
||||
} else if (params.row.promotionStatus == "END") {
|
||||
text = "已结束";
|
||||
color = "blue";
|
||||
} else if (params.row.promotionStatus == "CLOSE") {
|
||||
text = "已关闭";
|
||||
color = "red";
|
||||
}
|
||||
return h("div", [
|
||||
h(
|
||||
"Tag",
|
||||
{
|
||||
props: {
|
||||
color: color,
|
||||
},
|
||||
},
|
||||
text
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
goodsColumns: [
|
||||
{ type: "selection", width: 60, align: "center" },
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 120,
|
||||
},
|
||||
|
||||
{
|
||||
title: "库存",
|
||||
key: "quantity",
|
||||
minWidth: 40,
|
||||
},
|
||||
|
||||
{
|
||||
title: "拼团价格",
|
||||
key: "price",
|
||||
slot: "price",
|
||||
minWidth: 50,
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
minWidth: 50,
|
||||
align: "center",
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
size: "small",
|
||||
type: "error",
|
||||
ghost: true,
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.delGoods(params.index);
|
||||
},
|
||||
},
|
||||
},
|
||||
"删除"
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
goodsData: [], // 商品列表
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 关闭当前页面
|
||||
closeCurrentPage() {
|
||||
this.$store.commit("removeTag", "pintuan-goods");
|
||||
localStorage.storeOpenedList = JSON.stringify(
|
||||
this.$store.state.app.storeOpenedList
|
||||
);
|
||||
this.$router.go(-1);
|
||||
},
|
||||
save() {
|
||||
if (this.goodsData.length == 0) {
|
||||
this.$Modal.warning({ title: "提示", content: "请选择活动商品" });
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < this.goodsData.length; i++) {
|
||||
let data = this.goodsData[i];
|
||||
if (!data.price) {
|
||||
this.$Modal.warning({
|
||||
title: "提示",
|
||||
content: `请填写【${data.goodsName}】的价格`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.goodsData.forEach((item) => {
|
||||
item.promotionId = this.data[0].id;
|
||||
item.startTime = this.data[0].startTime;
|
||||
item.endTime = this.data[0].endTime;
|
||||
});
|
||||
this.data[0].promotionGoodsList = this.goodsData;
|
||||
this.submitLoading = true;
|
||||
editPintuan(this.data[0]).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("修改拼团商品成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
},
|
||||
init() {
|
||||
this.getDataList();
|
||||
this.getPintuanMsg();
|
||||
},
|
||||
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v - 1;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 0;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
handleReset() {
|
||||
// 重置
|
||||
// this.$refs.searchForm.resetFields();
|
||||
this.searchForm.pageNumber = 0;
|
||||
this.searchForm.promotionName = "";
|
||||
this.selectDate = null;
|
||||
|
||||
// 重新加载数据
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
// 获取选择数据
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
this.searchForm.pintuanId = this.$route.query.id;
|
||||
|
||||
getPintuanGoodsList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.goodsData = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getPintuanMsg() {
|
||||
// 获取拼团详情
|
||||
getPintuanDetail(this.$route.query.id).then((res) => {
|
||||
if (res.success) this.data.push(res.result);
|
||||
});
|
||||
},
|
||||
delGoods(index) {
|
||||
// 删除商品
|
||||
this.goodsData.splice(index, 1);
|
||||
},
|
||||
delAll() {
|
||||
if (this.selectCount <= 0) {
|
||||
this.$Message.warning("您还未选择要删除的数据");
|
||||
return;
|
||||
}
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除所选的 " + this.selectCount + " 条数据?",
|
||||
onOk: () => {
|
||||
let ids = [];
|
||||
this.selectList.forEach(function (e) {
|
||||
ids.push(e.id);
|
||||
});
|
||||
this.goodsData = this.goodsData.filter((item) => {
|
||||
return !ids.includes(item.id);
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
selectedGoodsData(item) {
|
||||
let ids = [];
|
||||
let list = [];
|
||||
this.goodsData.forEach((e) => {
|
||||
ids.push(e.id);
|
||||
});
|
||||
item.forEach((e) => {
|
||||
if (!ids.includes(e.id)) {
|
||||
list.push({
|
||||
goodsName: e.goodsName,
|
||||
price: e.price,
|
||||
originalPrice: e.price,
|
||||
quantity: e.quantity,
|
||||
storeId: e.storeId,
|
||||
sellerName: e.sellerName,
|
||||
thumbnail: e.thumbnail,
|
||||
skuId: e.id,
|
||||
categoryPath: e.categoryPath,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.goodsData.push(...list);
|
||||
},
|
||||
openSkuList() {
|
||||
this.$refs.skuSelect.open("goods");
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.operation {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
254
seller/src/views/promotion/seckill/seckill.vue
Normal file
254
seller/src/views/promotion/seckill/seckill.vue
Normal file
@@ -0,0 +1,254 @@
|
||||
<template>
|
||||
<div class="seckill">
|
||||
<Card>
|
||||
<Row>
|
||||
<Form
|
||||
ref="searchForm"
|
||||
:model="searchForm"
|
||||
inline
|
||||
:label-width="70"
|
||||
class="search-form"
|
||||
>
|
||||
<Form-item label="活动名称" prop="goodsName">
|
||||
<Input
|
||||
type="text"
|
||||
v-model="searchForm.promotionName"
|
||||
placeholder="请输入活动名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</Form-item>
|
||||
<Form-item label="活动状态" prop="promotionStatus">
|
||||
<Select
|
||||
v-model="searchForm.promotionStatus"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<Option value="NEW">未开始</Option>
|
||||
<Option value="START">已开始/上架</Option>
|
||||
<Option value="END">已结束/下架</Option>
|
||||
<Option value="CLOSE">紧急关闭/作废</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="活动时间">
|
||||
<DatePicker
|
||||
v-model="selectDate"
|
||||
type="daterange"
|
||||
clearable
|
||||
placeholder="选择起始时间"
|
||||
style="width: 200px"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
|
||||
</Form>
|
||||
</Row>
|
||||
|
||||
<Row class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="{ row }" slot="applyEndTime">
|
||||
{{ unixDate(row.applyEndTime) }}
|
||||
</template>
|
||||
<template slot-scope="{ row }" slot="hours">
|
||||
<Tag v-for="item in unixHours(row.hours)" :key="item">{{
|
||||
item
|
||||
}}</Tag>
|
||||
</template>
|
||||
<template slot-scope="{ row }" slot="action">
|
||||
<Button
|
||||
v-if="
|
||||
row.promotionStatus === 'NEW'
|
||||
"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="manage(row)"
|
||||
>管理</Button
|
||||
>
|
||||
</template>
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<Page
|
||||
:current="searchForm.pageNumber + 1"
|
||||
: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 { seckillList } from "@/api/promotion";
|
||||
export default {
|
||||
name: "goods",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 0, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "startTime",
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
title: "活动名称",
|
||||
key: "promotionName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "活动开始时间",
|
||||
key: "startTime",
|
||||
},
|
||||
{
|
||||
title: "报名截止时间",
|
||||
slot: "applyEndTime",
|
||||
},
|
||||
{
|
||||
title: "时间场次",
|
||||
slot: "hours",
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "promotionStatus",
|
||||
render: (h, params) => {
|
||||
let text = "未知",
|
||||
color = "default";
|
||||
if (params.row.promotionStatus == "NEW") {
|
||||
text = "未开始";
|
||||
color = "default";
|
||||
} else if (params.row.promotionStatus == "START") {
|
||||
text = "已开始";
|
||||
color = "green";
|
||||
} else if (params.row.promotionStatus == "END") {
|
||||
text = "已结束";
|
||||
color = "red";
|
||||
} else if (params.row.promotionStatus == "CLOSE") {
|
||||
text = "已关闭";
|
||||
color = "red";
|
||||
}
|
||||
return h("div", [
|
||||
h(
|
||||
"Tag",
|
||||
{
|
||||
props: {
|
||||
color: color,
|
||||
},
|
||||
},
|
||||
text
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
slot: "action",
|
||||
align: "center",
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v - 1;
|
||||
this.getDataList();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 0;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
|
||||
manage(row) {
|
||||
this.$router.push({ name: "seckill-goods", query: { id: row.id } });
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
if (this.selectDate && this.selectDate[0] && this.selectDate[1]) {
|
||||
this.searchForm.startTime = this.selectDate[0].getTime();
|
||||
this.searchForm.endTime = this.selectDate[1].getTime();
|
||||
} else {
|
||||
this.searchForm.startTime = null;
|
||||
this.searchForm.endTime = null;
|
||||
}
|
||||
// 带多条件搜索参数获取表单数据
|
||||
seckillList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
unixDate(time) {
|
||||
// 处理报名截止时间
|
||||
return this.$options.filters.unixToDate(new Date(time) / 1000);
|
||||
},
|
||||
unixHours(item) {
|
||||
// 处理小时场次
|
||||
let hourArr = item.split(",");
|
||||
for (let i = 0; i < hourArr.length; i++) {
|
||||
hourArr[i] += ":00";
|
||||
}
|
||||
return hourArr;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
watch: {
|
||||
$route(to, from) {
|
||||
if (to.fullPath == "/promotion/seckill") {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.seckill {
|
||||
.operation {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
.select-clear {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
.drop-down {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
444
seller/src/views/promotion/seckill/seckillGoods.vue
Normal file
444
seller/src/views/promotion/seckill/seckillGoods.vue
Normal file
@@ -0,0 +1,444 @@
|
||||
<template>
|
||||
<div class="seckill-goods">
|
||||
<Card>
|
||||
<Table border :columns="columns" :data="data">
|
||||
<template slot-scope="{ row }" slot="applyEndTime">
|
||||
{{ unixDate(row.applyEndTime) }}
|
||||
</template>
|
||||
<template slot-scope="{ row }" slot="hours">
|
||||
<Tag v-for="item in unixHours(row.hours)" :key="item">{{ item }}</Tag>
|
||||
</template>
|
||||
</Table>
|
||||
|
||||
<Row class="operation">
|
||||
<template v-if="promotionStatus == 'NEW'">
|
||||
<Button type="primary" @click="openSkuList">选择商品</Button>
|
||||
<Button @click="delAll">批量删除</Button>
|
||||
</template>
|
||||
</Row>
|
||||
<Row v-show="openTip">
|
||||
<Alert show-icon>
|
||||
已选择 <span class="select-count">{{ selectCount }}</span> 项
|
||||
</Alert>
|
||||
</Row>
|
||||
<Row class="operation">
|
||||
<Tabs type="card" v-model="tabIndex">
|
||||
<TabPane
|
||||
v-for="(tab, tabIndex) in goodsList"
|
||||
:key="tabIndex"
|
||||
:label="tab.hour"
|
||||
:name="tabIndex"
|
||||
>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="goodsColumns"
|
||||
:data="tab.list"
|
||||
:ref="'table' + tabIndex"
|
||||
sortable="custom"
|
||||
@on-selection-change="changeSelect"
|
||||
>
|
||||
<template slot-scope="{ row }" slot="originalPrice">
|
||||
<div>{{ row.originalPrice | unitPrice("¥") }}</div>
|
||||
</template>
|
||||
|
||||
<template slot-scope="{ row, index }" slot="quantity">
|
||||
<Input
|
||||
v-model="row.quantity"
|
||||
:disabled="row.promotionApplyStatus == 'PASS'"
|
||||
@input="
|
||||
goodsList[tabIndex].list[index].quantity = row.quantity
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template slot-scope="{ row, index }" slot="price">
|
||||
<Input
|
||||
v-model="row.price"
|
||||
:disabled="row.promotionApplyStatus == 'PASS'"
|
||||
@input="goodsList[tabIndex].list[index].price = row.price"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template slot-scope="{ row }" slot="promotionApplyStatus">
|
||||
<Badge
|
||||
status="success"
|
||||
v-if="row.promotionApplyStatus == 'PASS'"
|
||||
:text="promotionApplyStatus(row.promotionApplyStatus)"
|
||||
/>
|
||||
<Badge
|
||||
status="blue"
|
||||
v-if="row.promotionApplyStatus == 'APPLY'"
|
||||
:text="promotionApplyStatus(row.promotionApplyStatus)"
|
||||
/>
|
||||
<Badge
|
||||
status="error"
|
||||
v-if="row.promotionApplyStatus == 'REFUSE'"
|
||||
:text="promotionApplyStatus(row.promotionApplyStatus)"
|
||||
/>
|
||||
<span
|
||||
v-if="row.promotionApplyStatus == 'REFUSE'"
|
||||
@click="showReason(row.failReason)"
|
||||
class="reason"
|
||||
>(拒绝原因)</span
|
||||
>
|
||||
<Badge
|
||||
status="error"
|
||||
v-if="row.promotionApplyStatus == ''"
|
||||
:text="promotionApplyStatus(row.promotionApplyStatus)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template slot-scope="{ row }" slot="QRCode">
|
||||
<img
|
||||
v-if="row.QRCode"
|
||||
:src="row.QRCode || '../../../assets/lili.png'"
|
||||
width="50px"
|
||||
height="50px"
|
||||
alt=""
|
||||
/>
|
||||
</template>
|
||||
<template slot-scope="{ row, index }" slot="action">
|
||||
<Button
|
||||
type="error"
|
||||
v-if="row.promotionApplyStatus !== 'PASS'"
|
||||
:disabled="promotionStatus != 'NEW'"
|
||||
size="small"
|
||||
ghost
|
||||
@click="delGoods(index, row.id)"
|
||||
>删除</Button
|
||||
>
|
||||
</template>
|
||||
</Table>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</Row>
|
||||
|
||||
<Row class="operation">
|
||||
<Button @click="closeCurrentPage">返回</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
:loading="submitLoading"
|
||||
:disabled="promotionStatus != 'NEW'"
|
||||
@click="save"
|
||||
>提交</Button
|
||||
>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<sku-select
|
||||
ref="skuSelect"
|
||||
@selectedGoodsData="selectedGoodsData"
|
||||
></sku-select>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
seckillGoodsList,
|
||||
seckillDetail,
|
||||
setSeckillGoods,
|
||||
removeSeckillGoods,
|
||||
} from "@/api/promotion.js";
|
||||
import skuSelect from "@/views/lili-dialog";
|
||||
export default {
|
||||
components: {
|
||||
skuSelect,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
promotionStatus: "", // 活动状态
|
||||
openTip: true,
|
||||
loading: false, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 0, // 当前页数
|
||||
pageSize: 1000, // 页面大小
|
||||
},
|
||||
tabIndex: 0, // 选择商品的下标
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
data: [{}], // 表单数据
|
||||
columns: [
|
||||
{
|
||||
title: "活动名称",
|
||||
key: "promotionName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "活动开始时间",
|
||||
key: "startTime",
|
||||
},
|
||||
{
|
||||
title: "报名截止时间",
|
||||
slot: "applyEndTime",
|
||||
},
|
||||
{
|
||||
title: "时间场次",
|
||||
slot: "hours",
|
||||
},
|
||||
],
|
||||
goodsColumns: [
|
||||
{ type: "selection", width: 60, align: "center" },
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "商品价格",
|
||||
slot: "originalPrice",
|
||||
minWidth: 50,
|
||||
},
|
||||
{
|
||||
title: "库存",
|
||||
slot: "quantity",
|
||||
minWidth: 40,
|
||||
},
|
||||
{
|
||||
title: "活动价格",
|
||||
slot: "price",
|
||||
minWidth: 50,
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
slot: "promotionApplyStatus",
|
||||
minWidth: 30,
|
||||
},
|
||||
// {
|
||||
// title: "商品二维码",
|
||||
// slot: "QRCode",
|
||||
// },
|
||||
{
|
||||
title: "操作",
|
||||
slot: "action",
|
||||
minWidth: 50,
|
||||
},
|
||||
],
|
||||
goodsList: [] // 商品列表
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
// 关闭当前页面
|
||||
closeCurrentPage() {
|
||||
this.$store.commit("removeTag", "seckill-goods");
|
||||
localStorage.storeOpenedList = JSON.stringify(
|
||||
this.$store.state.app.storeOpenedList
|
||||
);
|
||||
this.$router.go(-1);
|
||||
},
|
||||
save() {
|
||||
// 提交
|
||||
// for(let i=0;i<this.goodsData.length;i++){
|
||||
// let data = this.goodsData[i]
|
||||
// if(!data.price){
|
||||
// this.$Modal.warning({
|
||||
// title:'提示',
|
||||
// content:`请填写【${data.goodsName}】的价格`
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
let list = JSON.parse(JSON.stringify(this.goodsList));
|
||||
let params = {
|
||||
seckillId: this.$route.query.id,
|
||||
applyVos: [],
|
||||
};
|
||||
list.forEach((e, index) => {
|
||||
e.list.forEach((i) => {
|
||||
// if(e.id) delete e.id
|
||||
params.applyVos.push(i);
|
||||
});
|
||||
});
|
||||
this.submitLoading = true;
|
||||
setSeckillGoods(params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res && res.success) {
|
||||
this.$Message.success("提交活动商品成功");
|
||||
this.closeCurrentPage();
|
||||
}
|
||||
});
|
||||
},
|
||||
init() {
|
||||
this.getSeckillMsg();
|
||||
},
|
||||
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
// 获取选择数据
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
|
||||
getDataList() {
|
||||
// 获取商品详情
|
||||
this.loading = true;
|
||||
this.searchForm.seckillId = this.$route.query.id;
|
||||
|
||||
// 处理过的时间 为‘1:00’
|
||||
let hours = this.unixHours(this.data[0].hours);
|
||||
hours.forEach((e) => {
|
||||
this.goodsList.push({
|
||||
hour: e,
|
||||
list: [],
|
||||
});
|
||||
});
|
||||
seckillGoodsList(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success && res.result) {
|
||||
let data = res.result.records;
|
||||
// 未处理时间 为'1'
|
||||
let noFilterhours = this.data[0].hours.split(",");
|
||||
if (data.length) {
|
||||
noFilterhours.forEach((e, index) => {
|
||||
data.forEach((i) => {
|
||||
if (i.timeLine == e) {
|
||||
this.goodsList[index].list.push(i);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getSeckillMsg() {
|
||||
// 获取活动详情
|
||||
seckillDetail(this.$route.query.id).then((res) => {
|
||||
if (res.success && res.result) {
|
||||
this.data = [];
|
||||
this.data.push(res.result);
|
||||
this.promotionStatus = res.result.promotionStatus;
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
delGoods(index, id) {
|
||||
// 删除商品
|
||||
if (id) {
|
||||
removeSeckillGoods(this.$route.query.id, id).then((res) => {
|
||||
if (res.success) {
|
||||
this.goodsList[this.tabIndex].list.splice(index, 1);
|
||||
this.$Message.success("删除成功!");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.goodsList[this.tabIndex].list.splice(index, 1);
|
||||
this.$Message.success("删除成功!");
|
||||
}
|
||||
},
|
||||
delAll() {
|
||||
if (this.selectCount <= 0) {
|
||||
this.$Message.warning("您还未选择要删除的数据");
|
||||
return;
|
||||
}
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除所选的 " + this.selectCount + " 条数据?",
|
||||
onOk: () => {
|
||||
let ids = [];
|
||||
this.selectList.forEach(function (e) {
|
||||
if (e.promotionApplyStatus !== 'PASS') {
|
||||
ids.push(e.id);
|
||||
}
|
||||
});
|
||||
this.goodsList[this.tabIndex].list = this.goodsList[
|
||||
this.tabIndex
|
||||
].list.filter((item) => {
|
||||
return !ids.includes(item.id);
|
||||
});
|
||||
removeSeckillGoods(this.$route.query.id, ids).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功!");
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
selectedGoodsData(item) {
|
||||
// 选择器添加商品
|
||||
let ids = [];
|
||||
let list = [];
|
||||
|
||||
this.goodsList[this.tabIndex].list.forEach((e) => {
|
||||
ids.push(e.id);
|
||||
});
|
||||
item.forEach((e) => {
|
||||
if (!ids.includes(e.id)) {
|
||||
list.push({
|
||||
goodsName: e.goodsName,
|
||||
price: e.price,
|
||||
originalPrice: e.price,
|
||||
promotionApplyStatus: "",
|
||||
quantity: e.quantity,
|
||||
seckillId: this.$route.query.id,
|
||||
storeId: e.storeId,
|
||||
storeName: e.storeName,
|
||||
skuId: e.id,
|
||||
timeLine: this.data[0].hours.split(",")[this.tabIndex],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.goodsList[this.tabIndex].list.push(...list);
|
||||
},
|
||||
openSkuList() {
|
||||
this.$refs.skuSelect.open("goods");
|
||||
},
|
||||
unixDate(time) {
|
||||
// 处理报名截止时间
|
||||
return this.$options.filters.unixToDate(new Date(time) / 1000);
|
||||
},
|
||||
unixHours(item) {
|
||||
if (item) {
|
||||
// 处理小时场次
|
||||
let hourArr = item.split(",");
|
||||
for (let i = 0; i < hourArr.length; i++) {
|
||||
hourArr[i] += ":00";
|
||||
}
|
||||
return hourArr;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
promotionApplyStatus(key) {
|
||||
switch (key) {
|
||||
case "APPLY":
|
||||
return "申请";
|
||||
break;
|
||||
case "PASS":
|
||||
return "通过";
|
||||
break;
|
||||
case "REFUSE":
|
||||
return "拒绝";
|
||||
break;
|
||||
default:
|
||||
return "未申请";
|
||||
break;
|
||||
}
|
||||
},
|
||||
showReason(reason) {
|
||||
this.$Modal.info({
|
||||
title: "拒绝原因",
|
||||
content: reason,
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.operation {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.reason {
|
||||
cursor: pointer;
|
||||
color: #2d8cf0;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
260
seller/src/views/shop/bill/accountStatementBill.vue
Normal file
260
seller/src/views/shop/bill/accountStatementBill.vue
Normal file
@@ -0,0 +1,260 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row @keydown.enter.native="handleSearch">
|
||||
<Form
|
||||
ref="searchForm"
|
||||
:model="searchForm"
|
||||
inline
|
||||
:label-width="70"
|
||||
class="search-form"
|
||||
>
|
||||
<Form-item label="开始时间" prop="startDay">
|
||||
<DatePicker
|
||||
type="date"
|
||||
v-model="searchForm.startDate"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Form-item label="结束时间" prop="endDate">
|
||||
<DatePicker
|
||||
type="date"
|
||||
v-model="searchForm.endDate"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
di
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
|
||||
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Shop from "@/api/shops";
|
||||
|
||||
export default {
|
||||
name: "accountStatementBill",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
startDate: "", // 起始时间
|
||||
endDate: "", // 终止时间
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
sn: "",
|
||||
sellerName: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
billPrice: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
{
|
||||
title: "账单号",
|
||||
key: "sn",
|
||||
minWidth: 250,
|
||||
tooltip: true },
|
||||
{
|
||||
title: "生成时间",
|
||||
key: "createTime",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "结算时间段",
|
||||
key: "startTime",
|
||||
width: 200,
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
return h('div', params.row.startTime +"~"+params.row.endTime)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "结算金额",
|
||||
key: "billPrice",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.billPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
title: "状态",
|
||||
key: "billStatus",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
if (params.row.billStatus == "OUT") {
|
||||
return h( "Badge", {props: { status: "success",text: "已出账" } })
|
||||
} else if (params.row.billStatus == "EXAMINE") {
|
||||
return h( "Badge", {props: { status: "success",text: "已审核" } })
|
||||
} else if (params.row.billStatus == "CHECK") {
|
||||
return h( "Badge", {props: { status: "success",text: "已对账" } })
|
||||
} else if (params.row.billStatus == "PAY") {
|
||||
return h( "Badge", {props: { status: "success",text: "已付款" } })
|
||||
}else if (params.row.billStatus == "COMPLETE") {
|
||||
return h( "Badge", {props: { status: "success",text: "已完成" } })
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"查看"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
this.searchForm.billStatus = "OUT"
|
||||
API_Shop.getBillPage(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
detail(v) {
|
||||
let id = v.id;
|
||||
this.$router.push({
|
||||
name: "bill-detail",
|
||||
query: { id: id },
|
||||
});
|
||||
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
/deep/ .ivu-col{
|
||||
min-height: 100vh;
|
||||
}
|
||||
</style>
|
||||
632
seller/src/views/shop/bill/billDetail.vue
Normal file
632
seller/src/views/shop/bill/billDetail.vue
Normal file
@@ -0,0 +1,632 @@
|
||||
<template>
|
||||
<div>
|
||||
<template>
|
||||
<Row>
|
||||
<i-col span="24">
|
||||
<Card>
|
||||
<p slot="title">商家信息</p>
|
||||
<div class="flex flex_align_item">
|
||||
<p>店铺名称:{{ bill.storeName }}</p>
|
||||
<p>银行开户名:{{ bill.bankAccountName }}</p>
|
||||
<p>银行账号:{{ bill.bankAccountNumber }}</p>
|
||||
<p>开户行支行名称:{{ bill.bankName }}</p>
|
||||
<p>支行联行号:{{ bill.bankCode }}</p>
|
||||
</div>
|
||||
</Card>
|
||||
</i-col>
|
||||
</Row>
|
||||
</template>
|
||||
<template>
|
||||
<Row>
|
||||
<i-col span="24">
|
||||
<Card>
|
||||
<p slot="title">账单详细</p>
|
||||
|
||||
<div class="tips-status">
|
||||
<span>商品状态</span>
|
||||
|
||||
<span class="theme_color">{{
|
||||
bill.billStatus | unixSellerBillStatus
|
||||
}}</span>
|
||||
|
||||
<Button
|
||||
v-if="bill.billStatus == 'OUT'"
|
||||
size="mini"
|
||||
@click="reconciliation()"
|
||||
type="primary"
|
||||
>对账</Button
|
||||
>
|
||||
</div>
|
||||
|
||||
<i-table :columns="columns" :data="data" stripe></i-table>
|
||||
</Card>
|
||||
</i-col>
|
||||
</Row>
|
||||
</template>
|
||||
<template>
|
||||
<Tabs active-key="tab" @on-click="clickTabs">
|
||||
<Tab-pane label="订单列表" name="order">
|
||||
<Card>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="orderColumns"
|
||||
:data="orderData"
|
||||
ref="table"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<Page
|
||||
:current="orderParam.pageNumber"
|
||||
:total="orderTotal"
|
||||
:page-size="orderParam.pageSize"
|
||||
@on-change="orderChangePage"
|
||||
@on-page-size-change="orderChangePageSize"
|
||||
size="small"
|
||||
show-total
|
||||
show-elevator
|
||||
></Page>
|
||||
</Row>
|
||||
</Card>
|
||||
</Tab-pane>
|
||||
<Tab-pane label="退单列表" name="refund">
|
||||
<Card>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="refundColumns"
|
||||
:data="refundData"
|
||||
ref="table"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<Page
|
||||
:current="refundParam.pageNumber"
|
||||
:total="refundTotal"
|
||||
:page-size="refundParam.pageSize"
|
||||
@on-change="refundChangePage"
|
||||
@on-page-size-change="refundChangePageSize"
|
||||
size="small"
|
||||
show-total
|
||||
show-elevator
|
||||
></Page>
|
||||
</Row>
|
||||
</Card>
|
||||
</Tab-pane>
|
||||
<Tab-pane label="分销费用列表" name="distribution">
|
||||
<Card>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="distributionColumns"
|
||||
:data="distributionData"
|
||||
ref="table"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<Page
|
||||
:current="distributionParam.pageNumber"
|
||||
:total="distributionTotal"
|
||||
:page-size="distributionParam.pageSize"
|
||||
@on-change="distributionChangePage"
|
||||
@on-page-size-change="distributionChangePageSize"
|
||||
size="small"
|
||||
show-total
|
||||
show-elevator
|
||||
></Page>
|
||||
</Row>
|
||||
</Card>
|
||||
</Tab-pane>
|
||||
</Tabs>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as filters from "@/utils/filters";
|
||||
import * as API_Shop from "@/api/shops";
|
||||
export default {
|
||||
name: "bill-detail",
|
||||
data() {
|
||||
return {
|
||||
columns: [
|
||||
{
|
||||
title: "项目",
|
||||
key: "name",
|
||||
width: 250,
|
||||
},
|
||||
{
|
||||
title: "值",
|
||||
key: "value",
|
||||
},
|
||||
],
|
||||
data: [ // 账单数据
|
||||
{
|
||||
name: "计算中",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "计算中",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "计算中",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "计算中",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "计算中",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "计算中",
|
||||
value: 0,
|
||||
},
|
||||
|
||||
{
|
||||
name: "计算公式",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "计算中",
|
||||
value: 0,
|
||||
}
|
||||
],
|
||||
id: "", // 账单id
|
||||
bill: {}, // 商家信息
|
||||
orderParam: {
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "id", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
flowType: "PAY",
|
||||
},
|
||||
orderColumns: [
|
||||
{
|
||||
title: "入账时间",
|
||||
key: "createTime",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "订单编号",
|
||||
key: "sn",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "订单金额",
|
||||
key: "finalPrice",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.finalPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "平台分佣",
|
||||
key: "commissionPrice",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.commissionPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "平台优惠券",
|
||||
key: "siteCouponPrice",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
if(params.row.siteCouponPrice == null){
|
||||
return h(
|
||||
"div",
|
||||
"-"
|
||||
);
|
||||
}else{
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.siteCouponPrice, "¥")
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "分销金额",
|
||||
key: "distributionRebate",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
if(params.row.distributionRebate == null){
|
||||
return h(
|
||||
"div",
|
||||
"-"
|
||||
);
|
||||
}else{
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.distributionRebate, "¥")
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "应结金额",
|
||||
key: "billPrice",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.billPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
],
|
||||
orderData: [], // 订单列表
|
||||
orderTotal: 0, // 订单数量
|
||||
//退单部分
|
||||
refundParam: {
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "id", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
flowType: "REFUND",
|
||||
},
|
||||
refundColumns: [
|
||||
{
|
||||
title: "退款时间",
|
||||
key: "createTime",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "退款流水编号",
|
||||
key: "sn",
|
||||
minWidth: 130
|
||||
},
|
||||
{
|
||||
title: "订单编号",
|
||||
key: "sn",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "退款金额",
|
||||
key: "finalPrice",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.finalPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "退还佣金",
|
||||
key: "commissionPrice",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
if(params.row.commissionPrice){
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.commissionPrice, "¥")
|
||||
);
|
||||
}else{
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(0, "¥")
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "退还平台优惠券",
|
||||
key: "siteCouponCommission",
|
||||
minWidth: 140
|
||||
},
|
||||
{
|
||||
title: "退还分销",
|
||||
key: "distributionRebate",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
if(params.row.distributionRebate == null){
|
||||
return h(
|
||||
"div",
|
||||
"-"
|
||||
);
|
||||
}else{
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.distributionRebate, "¥")
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "合计金额",
|
||||
key: "billPrice",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
if(params.row.billPrice == null){
|
||||
return h(
|
||||
"div",
|
||||
"-"
|
||||
);
|
||||
}else{
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.billPrice, "¥")
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
],
|
||||
refundData: [], // 退单数据
|
||||
refundTotal: 0, // 退单数量
|
||||
//分销佣金部分
|
||||
distributionParam: {
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "id", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
distributionColumns: [
|
||||
{
|
||||
title: "订单编号",
|
||||
key: "sn",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "交易金额",
|
||||
key: "finalPrice",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
minWidth: 120,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: "规格",
|
||||
key: "finalPrice",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.finalPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "店铺名称",
|
||||
key: "storeName",
|
||||
minWidth: 120
|
||||
},
|
||||
|
||||
{
|
||||
title: "佣金",
|
||||
key: "distributionRebate",
|
||||
minWidth: 120,
|
||||
render: (h, params) => {
|
||||
if(params.row.flowType === "退款" ){
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice("-"+params.row.distributionRebate, "¥")
|
||||
);
|
||||
}else{
|
||||
if(params.row.distributionRebate){
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.distributionRebate, "¥")
|
||||
);
|
||||
}else{
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(0, "¥")
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "时间",
|
||||
key: "createTime",
|
||||
minWidth: 120
|
||||
},
|
||||
],
|
||||
distributionData: [], // 分销数据
|
||||
distributionTotal: 0, // 分销总数
|
||||
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
'$route.query.id': function (val) {
|
||||
this.id = val;
|
||||
this.getBill();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickTabs(v) {
|
||||
if (v == "order") {
|
||||
this.orderParam.flowType = "PAY";
|
||||
this.getOrderList()
|
||||
} else if(v === "refund"){
|
||||
this.orderParam.flowType = "REFUND";
|
||||
this.getRefundList()
|
||||
}else{
|
||||
this.getDistributionList()
|
||||
}
|
||||
},
|
||||
//核对结算单
|
||||
reconciliation() {
|
||||
this.$Modal.confirm({
|
||||
title: "确认核对结算单",
|
||||
// 记得确认修改此处
|
||||
content: "您确认要核对此结算单么?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
API_Shop.reconciliation(this.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.code == 200) {
|
||||
this.$Message.success("账单核对成功");
|
||||
this.init();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
this.id = this.$route.query.id;
|
||||
this.getBill();
|
||||
},
|
||||
//订单列表部分
|
||||
orderChangePage(v) {
|
||||
this.orderParam.pageNumber = v;
|
||||
this.getOrderList()
|
||||
},
|
||||
orderChangePageSize(v) {
|
||||
this.orderParam.pageSize = v;
|
||||
this.getOrderList()
|
||||
},
|
||||
getOrderList(){
|
||||
API_Shop.getSellerFlow(this.id,this.orderParam).then((res) => {
|
||||
if (res.success) {
|
||||
this.orderData = res.result.records;
|
||||
this.orderTotal = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
//退单部分
|
||||
refundChangePage(v) {
|
||||
this.refundParam.pageNumber = v;
|
||||
this.getRefundList()
|
||||
},
|
||||
refundChangePageSize(v) {
|
||||
this.refundParam.pageSize = v;
|
||||
this.getRefundList()
|
||||
},
|
||||
getRefundList() {
|
||||
API_Shop.getSellerFlow(this.id, this.refundParam).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.result) {
|
||||
this.refundData = res.result.records;
|
||||
this.refundTotal = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
//分销费用列表
|
||||
distributionChangePage(v) {
|
||||
this.distributionParam.pageNumber = v;
|
||||
this.getDistributionList()
|
||||
},
|
||||
distributionChangePageSize(v) {
|
||||
this.distributionParam.pageSize = v;
|
||||
this.getDistributionList()
|
||||
},
|
||||
getDistributionList() {
|
||||
API_Shop.getDistributionFlow(this.id, this.distributionParam).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.result) {
|
||||
this.distributionData = res.result.records;
|
||||
this.distributionTotal = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
//获取结算单详细
|
||||
getBill(){
|
||||
API_Shop.getBillDetail(this.id).then((res) => {
|
||||
if (res.success) {
|
||||
this.bill = res.result;
|
||||
//初始化表格
|
||||
this.initTable();
|
||||
//初始化订单信息
|
||||
this.getOrderList();
|
||||
}
|
||||
});
|
||||
},
|
||||
initTable() {
|
||||
let bill = this.bill;
|
||||
this.data[0].name = "结算单号";
|
||||
this.data[0].value = bill.sn;
|
||||
|
||||
this.data[1].name = "起止日期";
|
||||
this.data[1].value = bill.startTime + "~" + bill.endTime;
|
||||
|
||||
this.data[2].name = "出帐日期";
|
||||
this.data[2].value = bill.createTime;
|
||||
|
||||
this.data[3].name = "当前状态";
|
||||
this.data[3].value = filters.unixSellerBillStatus(bill.billStatus);
|
||||
|
||||
this.data[4].name = "当前店铺";
|
||||
this.data[4].value = bill.storeName;
|
||||
|
||||
this.data[5].name = "平台打款时间";
|
||||
this.data[5].value = bill.payTime === null ? "未付款" : bill.payTime;
|
||||
|
||||
this.data[6].name = "结算金额";
|
||||
this.data[6].value = filters.unitPrice(bill.billPrice?bill.billPrice:0, "¥");
|
||||
|
||||
this.data[7].name = "结算详细";
|
||||
this.data[7].value =
|
||||
"最终结算金额(" +
|
||||
filters.unitPrice(bill.billPrice, "¥") +
|
||||
") = 订单付款总金额(" +
|
||||
filters.unitPrice(bill.orderPrice?bill.orderPrice:0, "¥") +
|
||||
") - 退单金额(" +
|
||||
filters.unitPrice(bill.refundPrice?bill.refundPrice:0, "¥") +
|
||||
")" +
|
||||
"- 平台收取佣金(" +
|
||||
filters.unitPrice(bill.commissionPrice?bill.commissionPrice:0, "¥") +
|
||||
") + 退单产生退还佣金金额(" +
|
||||
filters.unitPrice(bill.refundCommissionPrice?bill.refundCommissionPrice:0, "¥") +
|
||||
") - 分销返现支出(" +
|
||||
filters.unitPrice(bill.distributionCommission?bill.distributionCommission:0, "¥") +
|
||||
") + 退单分销返现返还(" +
|
||||
filters.unitPrice(bill.distributionRefundCommission?bill.distributionRefundCommission:0, "¥") +
|
||||
") - 平台优惠券支出(" +
|
||||
filters.unitPrice(bill.siteCouponCommission?bill.siteCouponCommission:0, "¥") +
|
||||
") + 退单平台优惠券返还(" +
|
||||
filters.unitPrice(bill.siteCouponRefundCommission?bill.siteCouponRefundCommission:0, "¥") +
|
||||
")";
|
||||
},
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.flex {
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
> p {
|
||||
width: 50%;
|
||||
margin: 15px 0;
|
||||
}
|
||||
}
|
||||
.tips-status {
|
||||
padding: 18px;
|
||||
> span {
|
||||
font-weight: bold;
|
||||
margin-right: 8px;
|
||||
}
|
||||
> span:nth-of-type(2) {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
264
seller/src/views/shop/bill/storeBill.vue
Normal file
264
seller/src/views/shop/bill/storeBill.vue
Normal file
@@ -0,0 +1,264 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row @keydown.enter.native="handleSearch">
|
||||
<Form
|
||||
ref="searchForm"
|
||||
:model="searchForm"
|
||||
inline
|
||||
:label-width="70"
|
||||
class="search-form"
|
||||
>
|
||||
<Form-item label="开始时间" prop="startDay">
|
||||
<DatePicker
|
||||
type="date"
|
||||
v-model="searchForm.startDate"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Form-item label="结束时间" prop="endDate">
|
||||
<DatePicker
|
||||
type="date"
|
||||
v-model="searchForm.endDate"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
di
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Form-item label="状态" prop="orderStatus">
|
||||
<Select v-model="searchForm.billStatus" placeholder="请选择" clearable style="width: 200px">
|
||||
<Option value="OUT">已出账</Option>
|
||||
<Option value="CHECK">已对账</Option>
|
||||
<Option value="COMPLETE">已完成</Option>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
|
||||
|
||||
</Form>
|
||||
</Row>
|
||||
<Row class="padding-row">
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Shop from "@/api/shops";
|
||||
|
||||
export default {
|
||||
name: "storeBill",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
startDate: "", // 起始时间
|
||||
endDate: "", // 终止时间
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
sn: "",
|
||||
sellerName: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
billPrice: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
{
|
||||
title: "账单号",
|
||||
key: "sn",
|
||||
minWidth: 250,
|
||||
tooltip: true },
|
||||
{
|
||||
title: "生成时间",
|
||||
key: "createTime",
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
title: "结算时间段",
|
||||
key: "startTime",
|
||||
width: 200,
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
return h('div', params.row.startTime +"~"+params.row.endTime)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "结算金额",
|
||||
key: "billPrice",
|
||||
minWidth: 100,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.billPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
title: "状态",
|
||||
key: "billStatus",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
if (params.row.billStatus == "OUT") {
|
||||
return h( "Badge", {props: { status: "success",text: "已出账" } })
|
||||
} else if (params.row.billStatus == "EXAMINE") {
|
||||
return h( "Badge", {props: { status: "success",text: "已审核" } })
|
||||
} else if (params.row.billStatus == "CHECK") {
|
||||
return h( "Badge", {props: { status: "success",text: "已对账" } })
|
||||
} else if (params.row.billStatus == "PAY") {
|
||||
return h( "Badge", {props: { status: "success",text: "已付款" } })
|
||||
}else if (params.row.billStatus == "COMPLETE") {
|
||||
return h( "Badge", {props: { status: "success",text: "已完成" } })
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "info",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.detail(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"查看"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
selectDateRange(v) {
|
||||
if (v) {
|
||||
this.searchForm.startDate = v[0];
|
||||
this.searchForm.endDate = v[1];
|
||||
}
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
API_Shop.getBillPage(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
detail(v) {
|
||||
let id = v.id;
|
||||
this.$router.push({
|
||||
name: "bill-detail",
|
||||
query: { id: id },
|
||||
});
|
||||
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
|
||||
</style>
|
||||
225
seller/src/views/shop/ship/logistics.vue
Normal file
225
seller/src/views/shop/ship/logistics.vue
Normal file
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Shop from "@/api/shops";
|
||||
|
||||
export default {
|
||||
name: "logistics",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
order: "desc", // 默认排序方式
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
sn: "",
|
||||
sellerName: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
billPrice: "",
|
||||
},
|
||||
// 表单验证规则
|
||||
formValidate: {},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
|
||||
{
|
||||
title: "物流公司",
|
||||
key: "name",
|
||||
minWidth: 120,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "selected",
|
||||
minWidth: 120,
|
||||
sortable: true,
|
||||
render: (h, params) => {
|
||||
if (params.row.selected === null || params.row.selected === "") {
|
||||
return h( "Badge", {props: { status: "error",text: "关闭" } })
|
||||
} else if (params.row.selected !== "") {
|
||||
return h( "Badge", {props: { status: "success",text: "开启" } })
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 200,
|
||||
render: (h, params) => {
|
||||
if(params.row.selected === null){
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "success",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.checked(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"开启"
|
||||
),
|
||||
]);
|
||||
}else{
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "error",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.unChecked(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"关闭"
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changeSort(e) {
|
||||
this.searchForm.sort = e.key;
|
||||
this.searchForm.order = e.order;
|
||||
if (e.order === "normal") {
|
||||
this.searchForm.order = "";
|
||||
}
|
||||
this.getDataList();
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
API_Shop.getLogistics().then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result;
|
||||
}
|
||||
});
|
||||
this.loading = false;
|
||||
},
|
||||
//物流公司选中
|
||||
checked(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认开启",
|
||||
// 记得确认修改此处
|
||||
content: "您确认开启此物流公司?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
API_Shop.logisticsChecked(v.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.code == 200) {
|
||||
this.$Message.success("物流公司开启成功");
|
||||
this.init();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//物流公司取消选中
|
||||
unChecked(v){
|
||||
this.$Modal.confirm({
|
||||
title: "确认关闭",
|
||||
// 记得确认修改此处
|
||||
content: "您确认关闭此物流公司?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
API_Shop.logisticsUnChecked(v.selected).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.code == 200) {
|
||||
this.$Message.success("物流公司关闭成功");
|
||||
this.init();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
// @import "@/styles/table-common.scss";
|
||||
.search {
|
||||
.operation {
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
.select-clear {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
|
||||
.drop-down {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
583
seller/src/views/shop/ship/shipTemplate.vue
Normal file
583
seller/src/views/shop/ship/shipTemplate.vue
Normal file
@@ -0,0 +1,583 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Row>
|
||||
<Button @click="refresh" >刷新</Button>
|
||||
<Button @click="add" type="primary">添加</Button>
|
||||
</Row>
|
||||
<Tabs @on-click="handleClickType" v-model="currentTab" style="margin-top: 10px">
|
||||
<TabPane label="运费模板" name="INFO">
|
||||
<table class="ncsc-default-table order m-b-30" :key="index" v-for="(item,index) in shipInfo">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="sep-row" colspan="20"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="20"><h3>{{item.name}}</h3>
|
||||
<span class="fr m-r-5">
|
||||
<time style="margin-right: 20px" title="最后编辑时间">
|
||||
<i class="icon-time"></i>{{item.updateTime}}
|
||||
</time>
|
||||
<Button @click="edit(item)" type="info" >修改</Button>
|
||||
<Button @click="remove(item.id)" type="error">删除</Button>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="w10 bdl"></td>
|
||||
<td class="cell-area tl">运送到</td>
|
||||
<td class="w150">首件(重)
|
||||
|
||||
</td>
|
||||
<td class="w150">运费</td>
|
||||
<td class="w150">续件(重)
|
||||
|
||||
</td>
|
||||
<td class="w150 bdr">运费</td>
|
||||
</tr>
|
||||
|
||||
<tr v-for="(children,index) in item.freightTemplateChildList">
|
||||
<td class="bdl"></td>
|
||||
<td class="cell-area tl" style="width: 60%">{{children.area}}</td>
|
||||
<td>
|
||||
{{children.firstCompany}}
|
||||
</td>
|
||||
<td>
|
||||
<span class="yuan">¥</span><span class="integer">{{children.firstPrice}}</span>
|
||||
</td>
|
||||
<td>
|
||||
{{children.continuedCompany}}
|
||||
</td>
|
||||
<td class="bdr">
|
||||
<span class="yuan">¥</span><span class="integer">{{children.continuedPrice}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
</TabPane>
|
||||
<TabPane v-if="csTab" :label=title :name=operation>
|
||||
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
|
||||
<FormItem label="模板名称" prop="name">
|
||||
<Input v-model="form.name" maxlength="10" clearable style="width: 20%"/>
|
||||
</FormItem>
|
||||
<FormItem label="计价方式" prop="pricingMethod">
|
||||
<RadioGroup v-model="form.pricingMethod">
|
||||
<Radio label="WEIGHT">按重量</Radio>
|
||||
<Radio label="NUM">按件数</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="详细设置">
|
||||
<div class="ncsu-trans-type" data-delivery="TRANSTYPE">
|
||||
<div class="entity">
|
||||
<div class="tbl-except">
|
||||
<table cellspacing="0" class="ncsc-default-table">
|
||||
<thead>
|
||||
<tr style="border-bottom: 1px solid #ddd;">
|
||||
<th class="w10"></th>
|
||||
<th class="tl">运送到</th>
|
||||
<th class="w10"></th>
|
||||
<th class="w50">首件(重)</th>
|
||||
<th class="w110">首费</th>
|
||||
<th class="w50">续件(重)</th>
|
||||
<th class="w110">续费</th>
|
||||
<th class="w150">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="bd-line" data-group="n1" v-for="(item,index) in form.freightTemplateChildList">
|
||||
<td></td>
|
||||
<td class="tl cell-area">
|
||||
<span class="area-group">
|
||||
<p style="display:inline-block">{{item.area}}</p></span>
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<Input class="text w40" type="text" v-model="item.firstCompany" maxlength="3" clearable/>
|
||||
</td>
|
||||
<td>
|
||||
<Input class="text w60" type="text" v-model="item.firstPrice" maxlength="6" clearable/><em
|
||||
class="add-on">
|
||||
元
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<Input class="text w40" type="text" v-model="item.continuedCompany" maxlength="6"
|
||||
clearable/>
|
||||
</td>
|
||||
<td>
|
||||
<Input class="text w60" type="text" v-model="item.continuedPrice" maxlength="6"
|
||||
clearable/><em class="add-on">
|
||||
元
|
||||
</em>
|
||||
</td>
|
||||
<td class="nscs-table-handle">
|
||||
<Button
|
||||
@click="editRegion(item)"
|
||||
type="info"
|
||||
size="small"
|
||||
style="margin-bottom: 5px"
|
||||
>修改
|
||||
</Button>
|
||||
<Button
|
||||
@click="removeTemplateChildren(index)"
|
||||
:loading="submitLoading"
|
||||
type="error"
|
||||
size="small"
|
||||
style="margin-bottom: 5px"
|
||||
>删除
|
||||
</Button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="tbl-attach p-5">
|
||||
<div class="div-error" v-if="saveError">
|
||||
<i class="fa fa-exclamation-circle" aria-hidden="true"></i>
|
||||
<Icon type="ios-information-circle-outline"/>
|
||||
指定地区城市为空或指定错误
|
||||
<Icon type="ios-information-circle-outline"/>
|
||||
首费应输入正确的金额
|
||||
<Icon type="ios-information-circle-outline"/>
|
||||
续费应输入正确的金额
|
||||
<Icon type="ios-information-circle-outline"/>
|
||||
首(续)件(重)费应输入大于0的整数
|
||||
</div>
|
||||
<Button
|
||||
@click="addShipTemplateChildren(index)"
|
||||
:loading="submitLoading"
|
||||
type="info"
|
||||
size="small"
|
||||
icon="ios-create-outline"
|
||||
style="margin-bottom: 5px"
|
||||
>为指定城市设置运费模板
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FormItem>
|
||||
<Form-item>
|
||||
<Button
|
||||
@click="handleSubmit"
|
||||
:loading="submitLoading"
|
||||
type="primary"
|
||||
style="margin-right:5px"
|
||||
>保存
|
||||
</Button>
|
||||
</Form-item>
|
||||
</Form>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<multiple-region ref="region" @selected="handleSelect" @closed="handleClose">
|
||||
|
||||
</multiple-region>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Shop from "@/api/shops";
|
||||
import multipleRegion from "@/views/lili-components/multiple-region";
|
||||
|
||||
|
||||
export default {
|
||||
name: "shipTemplate",
|
||||
components: {
|
||||
multipleRegion
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
item: "", //运费模板子模板
|
||||
shipInfo: {}, // 运费模板数据
|
||||
title: "添加运费模板", // 模态框标题
|
||||
operation: "add", // 操作状态
|
||||
currentTab: "", // 当前模板tab
|
||||
saveError: false, // 是否显示错误提示
|
||||
csTab: false, // 添加运费模板显示
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
name: "",
|
||||
pricingMethod: "WEIGHT"
|
||||
},
|
||||
formValidate: {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入模板名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
pricingMethod: [ // 计费方式
|
||||
{
|
||||
required: true,
|
||||
message: "请选择计费方式",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getData();
|
||||
},
|
||||
//切换tabPane
|
||||
handleClickType(v) {
|
||||
if (v == "INFO") {
|
||||
this.getData();
|
||||
this.csTab = false
|
||||
}
|
||||
},
|
||||
//添加运费模板
|
||||
add() {
|
||||
this.title = "添加运费模板"
|
||||
this.csTab = true
|
||||
this.operation = "ADD"
|
||||
this.currentTab = "ADD"
|
||||
this.saveError = false;
|
||||
this.form = {
|
||||
pricingMethod: "WEIGHT",
|
||||
name: "",
|
||||
freightTemplateChildList: [{
|
||||
area: "",
|
||||
areaId: "",
|
||||
firstCompany: "1",
|
||||
firstPrice: "",
|
||||
continuedCompany: "1",
|
||||
continuedPrice: ""
|
||||
}]
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
//修改运费模板
|
||||
edit(item) {
|
||||
this.title = "修改运费模板"
|
||||
this.csTab = true
|
||||
this.operation = "EDIT"
|
||||
this.currentTab = "EDIT"
|
||||
this.saveError = false;
|
||||
//给form赋值
|
||||
this.form = item
|
||||
},
|
||||
//选择地区
|
||||
editRegion(item){
|
||||
this.item = item
|
||||
|
||||
this.$refs.region.open(item)
|
||||
},
|
||||
//刷细数据
|
||||
refresh() {
|
||||
this.csTab = false
|
||||
this.operation = "INFO"
|
||||
this.currentTab = "INFO"
|
||||
this.getData()
|
||||
},
|
||||
//运费模板数据
|
||||
getData() {
|
||||
API_Shop.getShipTemplate().then((res) => {
|
||||
this.shipInfo = res.result
|
||||
});
|
||||
},
|
||||
|
||||
handleSelect(v) {
|
||||
let area = ""
|
||||
let areaId= ""
|
||||
if(v != ""){
|
||||
v.forEach((child, index) => {
|
||||
if(child.selectedList!=""){
|
||||
child.selectedList.forEach((child, index) => {
|
||||
area+=child.name +","
|
||||
areaId+=child.id +","
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
this.item.area = area
|
||||
this.item.areaId= areaId
|
||||
},
|
||||
//添加或者修改运费模板
|
||||
handleSubmit() {
|
||||
const headers = {
|
||||
"Content-Type": "application/json;charset=utf-8"
|
||||
}
|
||||
|
||||
this.$refs.form.validate((valid) => {
|
||||
const regNumber = /^\+?[1-9][0-9]*$/;
|
||||
const regMoney = /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/
|
||||
if (valid) {
|
||||
//校验运费模板详细信息
|
||||
for (let i = 0; i < this.form.freightTemplateChildList.length; i++) {
|
||||
if (this.form.freightTemplateChildList[i].area == ""
|
||||
|| this.form.freightTemplateChildList[i].firstCompany == ""
|
||||
|| this.form.freightTemplateChildList[i].firstPrice == ""
|
||||
|| this.form.freightTemplateChildList[i].continuedCompany == ""
|
||||
|| this.form.freightTemplateChildList[i].continuedPrice == "") {
|
||||
this.saveError = true;
|
||||
return
|
||||
}
|
||||
if (regNumber.test(this.form.freightTemplateChildList[i].firstCompany) == false
|
||||
|| regNumber.test(this.form.freightTemplateChildList[i].continuedCompany) == false
|
||||
|| regMoney.test(this.form.freightTemplateChildList[i].firstPrice) == false
|
||||
|| regMoney.test(this.form.freightTemplateChildList[i].continuedPrice) == false) {
|
||||
this.saveError = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.operation == "ADD") {
|
||||
API_Shop.addShipTemplate(this.form, headers).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("新增成功");
|
||||
this.operation = "INFO"
|
||||
this.currentTab = "INFO"
|
||||
this.csTab = false
|
||||
this.getData()
|
||||
}
|
||||
});
|
||||
} else {
|
||||
API_Shop.editShipTemplate(this.form.id, this.form, headers).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("新增成功");
|
||||
this.operation = "INFO"
|
||||
this.currentTab = "INFO"
|
||||
this.csTab = false
|
||||
this.getData()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
//添加子模板
|
||||
addShipTemplateChildren() {
|
||||
const params = {
|
||||
area: '',
|
||||
areaId: "",
|
||||
firstCompany: '1',
|
||||
firstPrice: '',
|
||||
continuedCompany: '1',
|
||||
continuedPrice: ''
|
||||
}
|
||||
this.form.freightTemplateChildList.push(params)
|
||||
},
|
||||
//删除一个子模板
|
||||
removeTemplateChildren(index) {
|
||||
if (Object.keys(this.form.freightTemplateChildList).length == 1) {
|
||||
this.$Message.success("必须保留一个子模板");
|
||||
return
|
||||
}
|
||||
this.form.freightTemplateChildList.splice(index, 1);
|
||||
},
|
||||
//删除运费模板
|
||||
remove(id) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
// 记得确认修改此处
|
||||
content: "您确认要删除此运费模板 ?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
API_Shop.deleteShipTemplate(id).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
}
|
||||
this.$Modal.remove();
|
||||
this.getData();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ncsc-default-table thead th {
|
||||
line-height: 20px;
|
||||
color: #555;
|
||||
background-color: #FAFAFA;
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
padding: 9px 0;
|
||||
border-bottom: solid 1px #DDD;
|
||||
}
|
||||
|
||||
.ncsc-default-table {
|
||||
line-height: 20px;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
tbody th {
|
||||
background-color: #FAFAFA;
|
||||
border: solid #E6E6E6;
|
||||
border-width: 1px 0;
|
||||
padding: 4px 0;
|
||||
|
||||
}
|
||||
|
||||
tbody td {
|
||||
color: #999;
|
||||
background-color: #FFF;
|
||||
text-align: center;
|
||||
padding: 6px 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.order tbody tr td {
|
||||
border-bottom: 1px solid #E6E6E6;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.order tbody tr td.bdr {
|
||||
border-right: 1px solid #E6E6E6;
|
||||
}
|
||||
|
||||
.order tbody tr th {
|
||||
border: solid 1px #DDD;
|
||||
}
|
||||
|
||||
.order tbody tr td.sep-row {
|
||||
height: 14px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.w10 {
|
||||
width: 10px !important;
|
||||
}
|
||||
|
||||
.tl {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.order tbody tr td.bdl {
|
||||
border-left: 1px solid #E6E6E6;
|
||||
}
|
||||
|
||||
.order tbody tr th h3 {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #555;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.m-r-5 {
|
||||
margin-right: 5px !important;
|
||||
}
|
||||
|
||||
.fr {
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
.m-b-30 {
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
Button {
|
||||
margin: 3px 5px 0px 5px;
|
||||
}
|
||||
|
||||
thead {
|
||||
display: table-header-group;
|
||||
vertical-align: middle;
|
||||
border-color: inherit;
|
||||
}
|
||||
|
||||
tr {
|
||||
display: table-row;
|
||||
vertical-align: inherit;
|
||||
border-color: inherit;
|
||||
}
|
||||
|
||||
caption, th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tl {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
colgroup {
|
||||
display: table-column-group;
|
||||
}
|
||||
|
||||
button, input, select, textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.bd-line td {
|
||||
border-bottom: solid 1px #EEE;
|
||||
}
|
||||
|
||||
.w40 {
|
||||
width: 60px !important;
|
||||
}
|
||||
|
||||
.w60 {
|
||||
width: 80px !important;
|
||||
}
|
||||
|
||||
Input[type="text"], Input[type="password"], Input.text, Input.password {
|
||||
display: inline-block;
|
||||
min-height: 20px;
|
||||
padding: 10px;
|
||||
border: solid 1px #E6E9EE;
|
||||
outline: 0 none;
|
||||
}
|
||||
|
||||
.add-on {
|
||||
line-height: 28px;
|
||||
background-color: #F6F7Fb;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: solid #E6E9EE;
|
||||
border-width: 1px 1px 1px 0;
|
||||
}
|
||||
|
||||
ncsc-default-table {
|
||||
line-height: 20px;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.ncsu-trans-type {
|
||||
background-color: #FFF;
|
||||
border: solid #DDD 1px;
|
||||
}
|
||||
|
||||
i, cite, em {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.cell-area {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.div-error {
|
||||
margin-left: 7px;
|
||||
margin-bottom: -8px;
|
||||
font-size: 15px;
|
||||
color: #F00;
|
||||
}
|
||||
</style>
|
||||
362
seller/src/views/shop/shopAddress.vue
Normal file
362
seller/src/views/shop/shopAddress.vue
Normal file
@@ -0,0 +1,362 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
|
||||
<Row class="operation">
|
||||
<Button @click="add" type="primary">添加</Button>
|
||||
</Row>
|
||||
<Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
ref="table"
|
||||
sortable="custom"
|
||||
@on-selection-change="changeSelect"
|
||||
></Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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>
|
||||
</Col>
|
||||
</Row>
|
||||
<Modal
|
||||
:title="modalTitle"
|
||||
v-model="modalVisible"
|
||||
:mask-closable="false"
|
||||
:width="500"
|
||||
>
|
||||
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
|
||||
<FormItem label="名称" prop="addressName">
|
||||
<Input v-model="form.addressName" clearable style="width: 90%"/>
|
||||
</FormItem>
|
||||
<FormItem label="详细地址" prop="address">
|
||||
<Input v-model="form.address" @on-focus="$refs.liliMap.showMap = true" clearable style="width: 90%"/>
|
||||
</FormItem>
|
||||
<FormItem label="联系电话" prop="mobile">
|
||||
<Input v-model="form.mobile" clearable style="width: 90%" maxlength="11"/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="modalVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="submitLoading" @click="handleSubmit"
|
||||
>提交
|
||||
</Button
|
||||
>
|
||||
</div>
|
||||
</Modal>
|
||||
<liliMap ref="liliMap" @getAddress="getAddress"></liliMap>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Shop from "@/api/shops";
|
||||
import { validateMobile } from "@/libs/validate";
|
||||
import liliMap from "@/views/my-components/map/index";
|
||||
|
||||
|
||||
export default {
|
||||
name: "shopAddress",
|
||||
components: {
|
||||
liliMap
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true, // 表单加载状态
|
||||
modalType: 0, // 添加或编辑标识
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
modalTitle: "", // 添加或编辑标题
|
||||
searchForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
},
|
||||
selectDate: null,
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
addressName: "",
|
||||
center: "",
|
||||
address:"",//详细地址
|
||||
mobile:"",//手机号码
|
||||
},
|
||||
|
||||
// 表单验证规则
|
||||
formValidate: {
|
||||
addressName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入地址名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
longitude: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入地址经度",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
latitude: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入地址纬度",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
mobile: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入地址纬度",
|
||||
trigger: "blur",
|
||||
},
|
||||
{ validator: validateMobile,
|
||||
trigger: "blur"
|
||||
}
|
||||
],
|
||||
address: [
|
||||
{
|
||||
required: true,
|
||||
message: " ",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
columns: [
|
||||
// 表头
|
||||
{
|
||||
title: "自提点名称",
|
||||
key: "addressName",
|
||||
minWidth: 120,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
title: "详细地址",
|
||||
key: "address",
|
||||
minWidth: 280
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
key: "createTime",
|
||||
minWidth: 120,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 200,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "success",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.edit(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"修改"
|
||||
),
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "error",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.deleteSubmit(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"删除"
|
||||
)
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
this.clearSelectAll();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
this.getDataList();
|
||||
},
|
||||
handleReset() {
|
||||
this.$refs.searchForm.resetFields();
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 10;
|
||||
// 重新加载数据
|
||||
this.getDataList();
|
||||
},
|
||||
clearSelectAll() {
|
||||
this.$refs.table.selectAll(false);
|
||||
},
|
||||
changeSelect(e) {
|
||||
this.selectList = e;
|
||||
this.selectCount = e.length;
|
||||
},
|
||||
//获取地址
|
||||
getAddress(item){
|
||||
|
||||
this.$set(this.form, 'address', item.addr)
|
||||
this.form.address = item.address
|
||||
this.form.center = item.position.lat + "," + item.position.lng
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
API_Shop.getShopAddress(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
this.total = this.data.length;
|
||||
this.loading = false;
|
||||
},
|
||||
//添加弹出框
|
||||
add() {
|
||||
this.$refs.form.resetFields()
|
||||
this.modalVisible = true
|
||||
this.modalTitle = "添加自提地址"
|
||||
},
|
||||
//修改弹出框
|
||||
edit(v) {
|
||||
this.modalType = 1
|
||||
this.modalVisible = true
|
||||
this.modalTitle = "修改自提地址"
|
||||
this.form.id = v.id
|
||||
this.form.address = v.address
|
||||
this.form.addressName = v.addressName
|
||||
this.form.mobile = v.mobile
|
||||
this.form.center = v.center
|
||||
this.form.longitude = v.center.split(',')[0]
|
||||
this.form.latitude = v.center.split(',')[1]
|
||||
},
|
||||
|
||||
//保存或者编辑
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
if (this.modalType == 0) {
|
||||
// 添加
|
||||
delete this.form.id;
|
||||
API_Shop.addShopAddress(this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("添加成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 编辑
|
||||
API_Shop.editShopAddress(this.form.id, this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("修改成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
//删除提交
|
||||
deleteSubmit(v){
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
// 记得确认修改此处
|
||||
content: "确认删除自提地址么?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
API_Shop.deleteShopAddress(v.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.code == 200) {
|
||||
this.$Message.success("此自自提地址已删除");
|
||||
this.init();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
// @import "@/styles/table-common.scss";
|
||||
.search {
|
||||
.operation {
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
|
||||
.select-count {
|
||||
font-weight: 600;
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
.select-clear {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
}
|
||||
|
||||
.drop-down {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
311
seller/src/views/shop/shopSetting.vue
Normal file
311
seller/src/views/shop/shopSetting.vue
Normal file
@@ -0,0 +1,311 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card style="margin-left: 10px">
|
||||
<Tabs @on-click="handleClickType">
|
||||
<TabPane label="基本信息" name="INFO">
|
||||
|
||||
<Form ref="form" :model="form" :label-width="100" :rules="formValidate">
|
||||
<FormItem label="店铺名称">
|
||||
<Input v-model="storeName" disabled clearable style="width: 20%" />
|
||||
</FormItem>
|
||||
<FormItem label="店铺地址" prop="address">
|
||||
<Input v-model="form.address" @on-focus="$refs.liliMap.showMap = true" clearable style="width: 20%" />
|
||||
</FormItem>
|
||||
<FormItem label="详细地址" prop="shopAddressDetail">
|
||||
<Input v-model="form.storeAddressDetail" clearable style="width: 20%" maxlength="50" />
|
||||
</FormItem>
|
||||
<FormItem label="店铺LOGO:">
|
||||
<upload-pic-thumb v-model="form.storeLogo" :multiple="false"></upload-pic-thumb>
|
||||
</FormItem>
|
||||
<FormItem label="店铺简介" prop="content" class="wangEditor">
|
||||
<editor v-model="form.storeDesc" style="width: 30%"></editor>
|
||||
</FormItem>
|
||||
<Form-item>
|
||||
<Button @click="handleSubmit" :loading="submitLoading" type="primary" style="margin-right:5px">修改
|
||||
</Button>
|
||||
</Form-item>
|
||||
</Form>
|
||||
</TabPane>
|
||||
<TabPane label="退货地址" name="REFUND_GOODS_ADDRESS">
|
||||
<Form ref="addressForm" :model="addressForm" :label-width="100" :rules="afterFormValidate">
|
||||
<FormItem label="收货人" prop="salesConsigneeName">
|
||||
<Input v-model="addressForm.salesConsigneeName" maxlength="11" clearable style="width: 20%" />
|
||||
</FormItem>
|
||||
<FormItem label="收货人电话" prop="salesConsigneeMobile">
|
||||
<Input v-model="addressForm.salesConsigneeMobile" maxlength="11" style="width: 20%" />
|
||||
</FormItem>
|
||||
<FormItem label="售后地址">
|
||||
<Input v-model="region" disabled style="width: 20%" v-if="showRegion == false" />
|
||||
<Button v-if="showRegion == false" @click="regionClick" :loading="submitLoading" type="primary" style="margin-left:8px">修改
|
||||
</Button>
|
||||
<region style="width: 20%" @selected="selectedRegion" v-if="showRegion == true" />
|
||||
</FormItem>
|
||||
<FormItem label="详细地址" prop="salesConsigneeDetail">
|
||||
<Input v-model="addressForm.salesConsigneeDetail" clearable style="width: 20%" maxlength="50" />
|
||||
</FormItem>
|
||||
|
||||
<Form-item>
|
||||
<Button @click="afterHandleSubmit" :loading="submitLoading" type="primary" style="margin-right:5px">修改
|
||||
</Button>
|
||||
</Form-item>
|
||||
</Form>
|
||||
</TabPane>
|
||||
<TabPane label="库存预警" name="STOCK_WARNING">
|
||||
|
||||
<Form ref="stockWarningForm" :model="stockWarningForm" :label-width="100" :rules="stockWarningFormValidate">
|
||||
<FormItem label="预警数" prop="stockWarning">
|
||||
<Input v-model="stockWarningForm.stockWarning" type="number" maxlength="6" clearable style="width: 20%" />
|
||||
</FormItem>
|
||||
<Form-item>
|
||||
<Button @click="stockWarningHandleSubmit" :loading="submitLoading" type="primary" style="margin-right:5px">修改
|
||||
</Button>
|
||||
</Form-item>
|
||||
</Form>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<liliMap ref="liliMap" @getAddress="getAddress"></liliMap>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Shop from "@/api/shops";
|
||||
import { validateMobile } from "@/libs/validate";
|
||||
import uploadPicThumb from "@/views/my-components/lili/upload-pic-thumb";
|
||||
import editor from "@/views/my-components/lili/editor";
|
||||
import liliMap from "@/views/my-components/map/index";
|
||||
import region from "@/views/lili-components/region";
|
||||
import * as RegExp from "@/libs/RegExp.js";
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
export default {
|
||||
name: "shopSetting",
|
||||
components: {
|
||||
uploadPicThumb,
|
||||
editor,
|
||||
liliMap,
|
||||
region,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showRegion: false, // 选择地址模态框显隐
|
||||
storeName: "", //店铺名称
|
||||
region: [], // 地区名称
|
||||
regionId: [], // 地区id
|
||||
addressForm: { // 退货地址
|
||||
salesConsigneeName: "", // 收货人姓名
|
||||
salesConsigneeMobile: "", // 收货人电话
|
||||
salesConsigneeAddressId: "", // 售后地址id,逗号分割
|
||||
salesConsigneeAddressPath: "",// 售后地址,逗号分割
|
||||
salesConsigneeDetail: "", // 详细地址
|
||||
},
|
||||
//库存预警form
|
||||
stockWarningForm: {
|
||||
stockWarning: "", // 库存预警数量
|
||||
},
|
||||
stockWarningFormValidate: {
|
||||
stockWarning: [
|
||||
{ required: true, message: "请输入库存预警数", trigger: "blur" },
|
||||
],
|
||||
},
|
||||
afterFormValidate: {
|
||||
salesConsigneeMobile: [
|
||||
{ required: true, message: "手机号不能为空", trigger: "blur" },
|
||||
{
|
||||
pattern: RegExp.mobile,
|
||||
trigger: "blur",
|
||||
message: "请输入正确的手机号",
|
||||
},
|
||||
],
|
||||
salesConsigneeName: [
|
||||
{ required: true, message: "请输入收货人", trigger: "blur" },
|
||||
],
|
||||
salesConsigneeDetail: [
|
||||
{ required: true, message: "请输入详细地址", trigger: "blur" },
|
||||
],
|
||||
},
|
||||
form: {
|
||||
// 添加或编辑表单对象初始化数据
|
||||
storeAddressPath: "", // 店铺地址中文
|
||||
center: "", // 经度 + 纬度
|
||||
longitude: "", //经度
|
||||
latitude: "", //纬度
|
||||
storeAddressDetail: "", //详细地址
|
||||
storeAddressIdPath: "", //地址
|
||||
storeDesc: "", // 店铺描述
|
||||
},
|
||||
|
||||
// 表单验证规则
|
||||
formValidate: {
|
||||
addressName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入地址名称",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
longitude: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入地址经度",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
latitude: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入地址纬度",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
mobile: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入地址纬度",
|
||||
trigger: "blur",
|
||||
},
|
||||
{
|
||||
validator: validateMobile,
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
storeAddressDetail: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入详细地址",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
},
|
||||
submitLoading: false, // 添加或编辑提交状态
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getShopInfo();
|
||||
},
|
||||
//获取店铺信息
|
||||
getShopInfo() {
|
||||
this.loading = true;
|
||||
API_Shop.getShopInfo().then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.form = res.result;
|
||||
this.$set(this.form, "address", res.result.storeAddressPath);
|
||||
this.storeName = res.result.storeName;
|
||||
this.form.center = res.result.storeCenter;
|
||||
Cookies.set("userInfo", JSON.stringify(res.result));
|
||||
//库存预警数赋值
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.stockWarningForm.stockWarning = res.result.stockWarning+"";
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//修改售后地址
|
||||
regionClick() {
|
||||
this.showRegion = true;
|
||||
this.regionId = "";
|
||||
},
|
||||
//重置
|
||||
handleReset() {
|
||||
this.$refs.form.resetFields();
|
||||
},
|
||||
//提交保存
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
API_Shop.saveShopInfo(this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("修改成功");
|
||||
this.getShopInfo();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//修改库存预警数
|
||||
stockWarningHandleSubmit() {
|
||||
this.$refs.stockWarningForm.validate((valid) => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
API_Shop.updateStockWarning(this.stockWarningForm).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("修改成功");
|
||||
this.getShopInfo();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 选中的地址
|
||||
selectedRegion(val) {
|
||||
this.region = val[1];
|
||||
this.regionId = val[0];
|
||||
},
|
||||
//tab切换
|
||||
handleClickType(v) {
|
||||
//退款
|
||||
if (v == "INFO") {
|
||||
this.getShopInfo();
|
||||
}
|
||||
//退货
|
||||
if (v == "REFUND_GOODS_ADDRESS") {
|
||||
this.getRefundGoodsAddress();
|
||||
}
|
||||
},
|
||||
//获取商家退货地址
|
||||
getRefundGoodsAddress() {
|
||||
API_Shop.getRefundGoodsAddress().then((res) => {
|
||||
if (res.result != null) {
|
||||
this.addressForm = res.result;
|
||||
this.regionId = res.result.salesConsigneeAddressId;
|
||||
this.region = res.result.salesConsigneeAddressPath;
|
||||
}
|
||||
});
|
||||
},
|
||||
//提交保存
|
||||
afterHandleSubmit() {
|
||||
if (this.regionId == "") {
|
||||
this.$Message.error("请选择地址");
|
||||
return;
|
||||
}
|
||||
this.$refs.addressForm.validate((valid) => {
|
||||
if (valid) {
|
||||
this.addressForm.salesConsigneeAddressPath = this.region;
|
||||
this.addressForm.salesConsigneeAddressId = this.regionId;
|
||||
this.submitLoading = true;
|
||||
API_Shop.saveRefundGoodsAddress(this.addressForm).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("修改成功");
|
||||
this.getRefundGoodsAddress();
|
||||
this.showRegion = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//获取地址
|
||||
getAddress(item) {
|
||||
this.$set(this.form, "address", item.addr);
|
||||
this.form.storeAddressPath = item.addr;
|
||||
this.form.storeAddressIdPath = item.addrId;
|
||||
this.form.center = item.position.lat + "," + item.position.lng;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
seller/src/views/statistics/goods.vue
Normal file
111
seller/src/views/statistics/goods.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div>
|
||||
<Affix :offset-top="100">
|
||||
<Card class="card fixed-bottom">
|
||||
<affixTime :closeShop="true" @selected="clickBreadcrumb"/>
|
||||
</Card>
|
||||
</Affix>
|
||||
<Card class="card">
|
||||
|
||||
<Tabs @on-click="handleClickType">
|
||||
<TabPane label="热门商品订单数量" name="NUM">
|
||||
<Table :columns="columns" :data="data"></Table>
|
||||
</TabPane>
|
||||
<TabPane label="热门商品订单金额" name="PRICE">
|
||||
<Table :columns="columns" :data="data"></Table>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as API_Goods from "@/api/goods";
|
||||
import Cookies from "js-cookie";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
params: { // 请求参数
|
||||
searchType: "LAST_SEVEN",
|
||||
year: "",
|
||||
month: "",
|
||||
storeId: JSON.parse(Cookies.get("userInfo")).id || '',
|
||||
type: "NUM"
|
||||
},
|
||||
columns: [ // 表格表头
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
},
|
||||
{
|
||||
title: "销售数量",
|
||||
key: "num",
|
||||
},
|
||||
{
|
||||
title: "销售金额",
|
||||
key: "price",
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.price)
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表格数据
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClickType(name) {
|
||||
this.params.type = name;
|
||||
this.getData();
|
||||
},
|
||||
|
||||
clickBreadcrumb(item, index) {
|
||||
let callback = item;
|
||||
let type = this.params.type;
|
||||
this.params = {...callback};
|
||||
this.params.type = type;
|
||||
this.getData();
|
||||
},
|
||||
getData() {
|
||||
Promise.all([API_Goods.goodsStatistics(this.params)]).then((res) => {
|
||||
if (res[0].result) {
|
||||
this.data = res[0].result;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getData();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.page-col {
|
||||
text-align: right;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.order-col {
|
||||
display: flex;
|
||||
|
||||
> div {
|
||||
margin-right: 8px;
|
||||
padding: 16px;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.order-list {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
806
seller/src/views/statistics/order.vue
Normal file
806
seller/src/views/statistics/order.vue
Normal file
@@ -0,0 +1,806 @@
|
||||
<template>
|
||||
|
||||
<div class="wrapper">
|
||||
<Affix :offset-top="100">
|
||||
<Card class="card fixed-bottom">
|
||||
|
||||
<affixTime @selected="clickBreadcrumb" />
|
||||
|
||||
</Card>
|
||||
</Affix>
|
||||
|
||||
<Card class="card">
|
||||
<div>
|
||||
<h4>交易概况</h4>
|
||||
<div class="flex">
|
||||
<div class="transactionList">
|
||||
<div class="transaction-item" v-for="(item,index) in transactionList" :key="index">
|
||||
<h4>{{item.label}}</h4>
|
||||
<div class="transaction-card" v-if="item.label=='转换'">
|
||||
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">访客数UV</div>
|
||||
<div class="card-item-value">{{overViewList.uvNum || 0}}</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">下单转化率</div>
|
||||
<div class="card-item-value">{{overViewList.orderConversionRate || '0%'}}</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">付款转化率</div>
|
||||
<div class="card-item-value">{{overViewList.paymentsConversionRate ||'0%'}}</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">全店转化率</div>
|
||||
<div class="card-item-value">{{overViewList.overallConversionRate || '0%'}}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="transaction-card" v-if="item.label=='订单'">
|
||||
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">下单笔数</div>
|
||||
<div class="card-item-value">{{overViewList.orderNum || 0}}</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">下单人数</div>
|
||||
<div class="card-item-value">{{overViewList.orderMemberNum || 0}}</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">下单金额</div>
|
||||
<div class="card-item-value">{{overViewList.orderAmount| unitPrice('¥') }}</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">付款笔数</div>
|
||||
<div class="card-item-value">{{overViewList.paymentsNum || 0}}</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">付款金额</div>
|
||||
<div class="card-item-value">{{overViewList.paymentAmount | unitPrice('¥')}}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="transaction-card" v-if="item.label=='退单'">
|
||||
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">退单笔数</div>
|
||||
<div class="card-item-value">{{overViewList.refundOrderNum || 0}}</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item-label">退单金额</div>
|
||||
<div class="card-item-value">{{overViewList.refundOrderPrice || 0}}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shap">
|
||||
<div id="overViewChart">
|
||||
<!-- 上 -->
|
||||
<div class="block">
|
||||
<div class="box">
|
||||
<span>访客数</span>
|
||||
<span>{{overViewList.uvNum || 0}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 中 -->
|
||||
<div class="block">
|
||||
<div class="box">
|
||||
<span>下单笔数</span>
|
||||
<span>{{overViewList.orderNum || 0}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 下 -->
|
||||
<div class="block">
|
||||
<div class="box">
|
||||
<span>付款笔数</span>
|
||||
<span>{{overViewList.paymentsNum || 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 线 -->
|
||||
<div class="rightBorder">
|
||||
|
||||
</div>
|
||||
<div class="leftTopBorder">
|
||||
|
||||
</div>
|
||||
<div class="leftBottomBorder">
|
||||
|
||||
</div>
|
||||
<!--数据 -->
|
||||
<div class="leftTopTips">
|
||||
<div>下单转化率 </div>
|
||||
<div>{{overViewList.orderConversionRate || '0%' }}</div>
|
||||
</div>
|
||||
<div class="leftBottomTips">
|
||||
<div>付款转化率</div>
|
||||
<div>{{overViewList.paymentsConversionRate || '0%'}}</div>
|
||||
</div>
|
||||
<div class="rightTips">
|
||||
<div>整体转换率</div>
|
||||
<div>{{overViewList.overallConversionRate || '0%'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card class="card">
|
||||
<div>
|
||||
<h4>交易趋势</h4>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<div id="orderChart"></div>
|
||||
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card class="card">
|
||||
<div>
|
||||
<h4>订退单统计</h4>
|
||||
<div class="breadcrumb" style="margin-bottom:20px;">
|
||||
<span @click="clickTab(item,index)" :class="{'active':item.selected}" v-for="(item,index) in orderType" :key="index"> {{item.title}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<Table stripe :columns="columns" :data="data"></Table>
|
||||
|
||||
</div>
|
||||
<Page @on-change="(index)=>{refundParams.pageNumber = index}" @on-page-size-change="(size)=>{refundParams.pageSize= size}" class="page" show-total show-elevator :total="total" />
|
||||
|
||||
</div>
|
||||
|
||||
</Card>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as API_Goods from "@/api/goods";
|
||||
import { Chart } from "@antv/g2";
|
||||
|
||||
import orderRow from "./order/orderDetail";
|
||||
import refundRow from "./order/refundOrder";
|
||||
import affixTime from "@/views/lili-components/affix-time";
|
||||
import Cookies from "js-cookie";
|
||||
export default {
|
||||
components: { orderRow, refundRow, affixTime },
|
||||
|
||||
data() {
|
||||
return {
|
||||
total: "0", // 订单总数
|
||||
orderType: [ // tab切换状态
|
||||
{
|
||||
title: "订单",
|
||||
selected: true,
|
||||
},
|
||||
{
|
||||
title: "退单",
|
||||
selected: false,
|
||||
},
|
||||
],
|
||||
// 订单状态
|
||||
orderStatusList: {
|
||||
UNDELIVERED: "待发货",
|
||||
UNPAID: "未付款",
|
||||
PAID: "已付款",
|
||||
DELIVERED: "已发货",
|
||||
CANCELLED: "已取消",
|
||||
COMPLETED: "已完成",
|
||||
TAKE: "已完成",
|
||||
},
|
||||
|
||||
serviceTypeList: { // 服务类型
|
||||
CANCEL: "取消",
|
||||
RETURN_GOODS: "退货",
|
||||
EXCHANGE_GOODS: "换货",
|
||||
RETURN_MONEY: "退款",
|
||||
},
|
||||
serviceStatusList: { // 服务类型
|
||||
APPLY: "申请售后",
|
||||
PASS: "通过售后",
|
||||
REFUSE: "拒绝售后",
|
||||
BUYER_RETURN: "买家退货,待卖家收货",
|
||||
SELLER_RE_DELIVERY: "商家换货/补发",
|
||||
SELLER_CONFIRM: "卖家确认收货",
|
||||
SELLER_TERMINATION: "卖家终止售后",
|
||||
BUYER_CONFIRM: "买家确认收货",
|
||||
BUYER_CANCEL: "买家取消售后",
|
||||
WAIT_REFUND: "等待平台退款",
|
||||
COMPLETE: "完成售后",
|
||||
},
|
||||
//
|
||||
|
||||
data: [], //定退单存储值
|
||||
|
||||
columns: [], // 定退单title
|
||||
|
||||
orderColumns: [ // 订单表头
|
||||
{
|
||||
type: "expand",
|
||||
width: 50,
|
||||
render: (h, params) => {
|
||||
return h(orderRow, {
|
||||
props: {
|
||||
res: params.row,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "商家名称",
|
||||
key: "storeName",
|
||||
},
|
||||
{
|
||||
title: "用户名",
|
||||
key: "memberName",
|
||||
},
|
||||
|
||||
{
|
||||
title: "订单状态",
|
||||
key: "orderStatus",
|
||||
render: (h, params) => {
|
||||
return h("div", this.orderStatusList[params.row.orderStatus]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
key: "createTime",
|
||||
},
|
||||
|
||||
{
|
||||
title: "支付时间",
|
||||
key: "paymentTime",
|
||||
render: (h, params) => {
|
||||
return h("div", params.row.paymentTime || "暂无");
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "价格",
|
||||
key: "flowPrice",
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.flowPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
refundColumns: [ // 退货单表头
|
||||
{
|
||||
type: "expand",
|
||||
width: 50,
|
||||
render: (h, params) => {
|
||||
return h(refundRow, {
|
||||
props: {
|
||||
res: params.row,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "商品图片",
|
||||
key: "goodsImage",
|
||||
render: (h, params) => {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: params.row.goodsImage,
|
||||
},
|
||||
style: {
|
||||
width: "60px",
|
||||
verticalAlign: "middle",
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
},
|
||||
{
|
||||
title: "商家名称",
|
||||
key: "sellerName",
|
||||
},
|
||||
{
|
||||
title: "售后单类型",
|
||||
key: "serviceType",
|
||||
render: (h, params) => {
|
||||
return h("div", this.serviceTypeList[params.row.serviceType]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "售后单状态",
|
||||
key: "serviceStatus",
|
||||
render: (h, params) => {
|
||||
return h("div", this.serviceStatusList[params.row.serviceStatus]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "退款时间",
|
||||
key: "refundTime",
|
||||
render: (h, params) => {
|
||||
return h("div", params.row.refundTime || "暂无");
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "申请退款金额",
|
||||
key: "applyRefundPrice",
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
"¥" +
|
||||
(params.row.applyRefundPrice ? params.row.applyRefundPrice : 0)
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "申请原因",
|
||||
key: "reason",
|
||||
},
|
||||
{
|
||||
title: "实际金额",
|
||||
key: "flowPrice",
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
this.$options.filters.unitPrice(params.row.flowPrice, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
// 交易概况
|
||||
transactionList: [
|
||||
{
|
||||
label: "转换",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
label: "订单",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
label: "退单",
|
||||
value: "",
|
||||
},
|
||||
],
|
||||
|
||||
chartList: [], // 绘制订单图表数据
|
||||
orderChart: "", //订单图表
|
||||
|
||||
overViewList: {}, // 绘制订单统计概览
|
||||
overViewChart: "", //订单订单统计概览图标
|
||||
|
||||
// 时间
|
||||
dateList: [
|
||||
{
|
||||
title: "今天",
|
||||
selected: false,
|
||||
value: "TODAY",
|
||||
},
|
||||
{
|
||||
title: "昨天",
|
||||
selected: false,
|
||||
value: "YESTERDAY",
|
||||
},
|
||||
{
|
||||
title: "最近7天",
|
||||
selected: true,
|
||||
value: "LAST_SEVEN",
|
||||
},
|
||||
{
|
||||
title: "最近30天",
|
||||
selected: false,
|
||||
value: "LAST_THIRTY",
|
||||
},
|
||||
],
|
||||
|
||||
// 订单传参
|
||||
orderParams: {
|
||||
searchType: "LAST_SEVEN", // TODAY , YESTERDAY , LAST_SEVEN , LAST_THIRTY
|
||||
year: "",
|
||||
storeId: JSON.parse(Cookies.get("userInfo")).id || '',
|
||||
memberId: "",
|
||||
},
|
||||
// 订单概念
|
||||
overViewParams: {
|
||||
month: "",
|
||||
searchType: "LAST_SEVEN", // TODAY , YESTERDAY , LAST_SEVEN , LAST_THIRTY
|
||||
storeId: JSON.parse(Cookies.get("userInfo")).id || '',
|
||||
year: "",
|
||||
},
|
||||
defaultParams: {
|
||||
month: "",
|
||||
searchType: "LAST_SEVEN", // TODAY , YESTERDAY , LAST_SEVEN , LAST_THIRTY
|
||||
storeId: JSON.parse(Cookies.get("userInfo")).id || '',
|
||||
year: "",
|
||||
},
|
||||
|
||||
refundIndex: 0, // 当前退单下标详情
|
||||
// 退单订单
|
||||
refundParams: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
searchType: "LAST_SEVEN",
|
||||
storeId:JSON.parse(Cookies.get("userInfo")).id || '',
|
||||
year: "",
|
||||
},
|
||||
|
||||
//
|
||||
//
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
refundParams: {
|
||||
handler() {
|
||||
console.log(this.refundIndex);
|
||||
if (this.refundIndex == 1) {
|
||||
this.getOrderRefundList();
|
||||
} else {
|
||||
this.getOrderList();
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immediate: true,
|
||||
},
|
||||
orderParams: {
|
||||
handler() {
|
||||
this.initOrderChartList();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
overViewParams: {
|
||||
handler() {
|
||||
this.initOrderOverViewList();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clickTab(item, index) {
|
||||
this.refundIndex = index;
|
||||
this.orderType.forEach((res) => {
|
||||
res.selected = false;
|
||||
});
|
||||
if (item.title == "退单") {
|
||||
this.getOrderRefundList();
|
||||
} else {
|
||||
this.getOrderList();
|
||||
}
|
||||
item.selected = true;
|
||||
},
|
||||
// 订单图
|
||||
initOrderChart() {
|
||||
// 默认已经加载 legend-filter 交互
|
||||
let data = this.chartList;
|
||||
|
||||
this.orderChart.data(data);
|
||||
this.orderChart.scale({
|
||||
finalPrice: {
|
||||
range: [0, 1],
|
||||
nice: true,
|
||||
},
|
||||
});
|
||||
this.orderChart.tooltip({
|
||||
showCrosshairs: true,
|
||||
shared: true,
|
||||
});
|
||||
this.orderChart.axis("finalPrice", {
|
||||
label: {
|
||||
formatter: (val) => {
|
||||
return val + "元";
|
||||
},
|
||||
},
|
||||
});
|
||||
this.orderChart
|
||||
.line()
|
||||
.position("createTime*price")
|
||||
|
||||
.shape("smooth");
|
||||
|
||||
this.orderChart
|
||||
.point()
|
||||
.position("createTime*price")
|
||||
|
||||
.shape("circle")
|
||||
.style({
|
||||
stroke: "#fff",
|
||||
lineWidth: 1,
|
||||
});
|
||||
this.orderChart.render();
|
||||
},
|
||||
|
||||
clickBreadcrumb(item, index) {
|
||||
let callback = JSON.parse(JSON.stringify(item));
|
||||
|
||||
this.orderParams = callback;
|
||||
|
||||
this.overViewParams = callback;
|
||||
this.refundParams = callback;
|
||||
},
|
||||
|
||||
// 实例化订单概览
|
||||
async initOrderOverViewList() {
|
||||
const res = await API_Goods.getOrderOverView(this.overViewParams);
|
||||
if (res.success) {
|
||||
this.overViewList = res.result;
|
||||
console.log(res.result);
|
||||
}
|
||||
},
|
||||
// 实例化订单图表
|
||||
async initOrderChartList(name) {
|
||||
const res = await API_Goods.getOrderChart(this.orderParams);
|
||||
if (res.success) {
|
||||
this.chartList = res.result;
|
||||
|
||||
if (!this.orderChart) {
|
||||
this.orderChart = new Chart({
|
||||
container: "orderChart",
|
||||
autoFit: true,
|
||||
height: 500,
|
||||
padding: [70, 35, 70, 35],
|
||||
});
|
||||
}
|
||||
|
||||
this.initOrderChart(); //订单表
|
||||
}
|
||||
},
|
||||
// 统计相关订单统计
|
||||
async getOrderList() {
|
||||
const res = await API_Goods.statisticsOrderList(this.refundParams);
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.columns = this.orderColumns;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
},
|
||||
|
||||
// 统计相关退单统计
|
||||
async getOrderRefundList() {
|
||||
const res = await API_Goods.statisticsOrderRefundList(this.refundParams);
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.columns = this.refundColumns;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
},
|
||||
|
||||
// 实例化初始值
|
||||
initBaseParams() {
|
||||
let data = new Date();
|
||||
this.getOrderList();
|
||||
this.orderParams.year = data.getFullYear();
|
||||
this.overViewParams.year = data.getFullYear();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.initBaseParams();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.active {
|
||||
color: $theme_color;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
bottom: -5px;
|
||||
left: 0;
|
||||
background: $theme_color;
|
||||
}
|
||||
}
|
||||
.breadcrumb{
|
||||
span{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.page-col {
|
||||
text-align: right;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.wrapper {
|
||||
padding-bottom: 200px;
|
||||
}
|
||||
.page {
|
||||
text-align: right;
|
||||
margin: 20px 0;
|
||||
}
|
||||
#overViewChart {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
margin-left: 20px;
|
||||
> .leftTopTips {
|
||||
position: absolute;
|
||||
top: 68px;
|
||||
left: -2px;
|
||||
width: 85px;
|
||||
text-align: center;
|
||||
background: rgb(255, 255, 255);
|
||||
z-index: 1;
|
||||
padding: 5px 0px;
|
||||
}
|
||||
> .leftBottomTips {
|
||||
position: absolute;
|
||||
bottom: 100px;
|
||||
left: -2px;
|
||||
width: 85px;
|
||||
text-align: center;
|
||||
background: rgb(255, 255, 255);
|
||||
z-index: 1;
|
||||
padding: 5px 0px;
|
||||
}
|
||||
> .rightTips {
|
||||
position: absolute;
|
||||
bottom: 240px;
|
||||
right: 0px;
|
||||
width: 85px;
|
||||
text-align: center;
|
||||
background: rgb(255, 255, 255);
|
||||
z-index: 1;
|
||||
padding: 5px 0px;
|
||||
}
|
||||
> .rightBorder {
|
||||
width: 110px;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 40px;
|
||||
border: 2px solid #d9d9d9;
|
||||
border-left: 0;
|
||||
height: 280px;
|
||||
}
|
||||
> .leftTopBorder {
|
||||
border: 2px solid #d9d9d9;
|
||||
height: 118px;
|
||||
width: 56px;
|
||||
position: absolute;
|
||||
left: 40px;
|
||||
top: 30px;
|
||||
border-right: 0;
|
||||
}
|
||||
> .leftBottomBorder {
|
||||
width: 108px;
|
||||
border: 2px solid #d9d9d9;
|
||||
height: 150px;
|
||||
position: absolute;
|
||||
bottom: 45px;
|
||||
left: 40px;
|
||||
border-right: 0;
|
||||
}
|
||||
> .block {
|
||||
height: 0px;
|
||||
border-left: 30px solid transparent;
|
||||
border-right: 30px solid transparent;
|
||||
position: relative;
|
||||
background: rgb(255, 255, 255);
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
> .block:nth-of-type(1) {
|
||||
width: 240px;
|
||||
border-top: 90px solid #ff4646;
|
||||
> .box {
|
||||
left: -30px;
|
||||
top: -90px;
|
||||
width: 240px;
|
||||
height: 90px;
|
||||
}
|
||||
}
|
||||
> .block:nth-of-type(2) {
|
||||
width: 172px;
|
||||
border-top: 100px solid #ff8585;
|
||||
margin-top: 10px;
|
||||
> .box {
|
||||
left: -29px;
|
||||
top: -100px;
|
||||
width: 172px;
|
||||
height: 100px;
|
||||
}
|
||||
}
|
||||
> .block:nth-of-type(3) {
|
||||
width: 100px;
|
||||
margin-top: 10px;
|
||||
border-top: 150px solid #ffb396;
|
||||
border-left: 50px solid transparent;
|
||||
border-right: 50px solid transparent;
|
||||
|
||||
> .box {
|
||||
left: -50px;
|
||||
top: -150px;
|
||||
width: 100px;
|
||||
height: 120px;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
/deep/ .box {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> span {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.transaction-item {
|
||||
margin: 10px 0;
|
||||
}
|
||||
h4 {
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
.transactionList {
|
||||
flex: 7;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.shap {
|
||||
width: 400px;
|
||||
margin-left: 20px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.transaction-card {
|
||||
height: 120px;
|
||||
border-radius: 0.4em;
|
||||
display: flex;
|
||||
background: #f3f5f7;
|
||||
}
|
||||
.card-item-label {
|
||||
font-weight: bold;
|
||||
font-size: #666;
|
||||
font-size: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.card-item-value {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: $theme_color;
|
||||
}
|
||||
.card-item {
|
||||
height: 100%;
|
||||
|
||||
width: 20%;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.order-col {
|
||||
display: flex;
|
||||
> div {
|
||||
margin-right: 8px;
|
||||
padding: 16px;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
.order-list {
|
||||
display: flex;
|
||||
}
|
||||
.tips {
|
||||
margin: 0 8px;
|
||||
}
|
||||
.card {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
151
seller/src/views/statistics/order/orderDetail.vue
Normal file
151
seller/src/views/statistics/order/orderDetail.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
|
||||
<div class="shop">
|
||||
<h3>订单详情</h3>
|
||||
<div class="shop-item">
|
||||
<div class="label-item">
|
||||
<span>订单来源</span>
|
||||
<span>{{res.clientType}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>订单状态</span>
|
||||
<span>{{orderStatusList[res.orderStatus]}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>付款状态</span>
|
||||
<span>{{res.payStatus == "UNPAID"
|
||||
? "未付款"
|
||||
: res.payStatus == "PAID"
|
||||
? "已付款"
|
||||
: ""}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>支付时间</span>
|
||||
<span>{{res.paymentTime || '暂无'}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>支付方式</span>
|
||||
<span>{{res.paymentMethod == "ONLINE" ? "在线支付" : ""
|
||||
}}{{ res.paymentMethod == "ALIPAY" ? "支付宝" : res.paymentMethod == "BANK_TRANSFER" ? "银行卡" : "" || '暂无'}}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="shop-item">
|
||||
<div class="label-item">
|
||||
<span>用户名</span>
|
||||
<span>{{res.memberName}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>店铺名称</span>
|
||||
<span>{{res.storeName}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>创建时间</span>
|
||||
<span>{{res.createTime}}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<h3>商品详情</h3>
|
||||
<div class="shop-item">
|
||||
|
||||
<div class="goods-item" v-for="(item,index) in res.orderItems" :key="index">
|
||||
<div class="goods-img">
|
||||
<img class="img" :src="item.image" alt="">
|
||||
</div>
|
||||
<div class="goods-title">
|
||||
<div>{{item.name}}</div>
|
||||
<div>{{'x'+item.num}}</div>
|
||||
<div class="goods-price">{{res.flowPrice | unitPrice('¥')}}</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="count-price">
|
||||
<div class="label-item">
|
||||
<span>总价格</span>
|
||||
<span class="flowPrice">{{res.flowPrice | unitPrice('¥')}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
orderStatusList: {
|
||||
UNDELIVERED: "待发货",
|
||||
UNPAID: "未付款",
|
||||
PAID: "已付款",
|
||||
DELIVERED: "已发货",
|
||||
CANCELLED: "已取消",
|
||||
COMPLETED: "已完成",
|
||||
TAKE: "已完成",
|
||||
},
|
||||
};
|
||||
},
|
||||
props: ["res"],
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
}
|
||||
.shop {
|
||||
padding: 10px 0;
|
||||
background: #fff;
|
||||
}
|
||||
.shop-item {
|
||||
display: flex;
|
||||
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
h3 {
|
||||
margin: 20px 16px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.goods-price {
|
||||
font-size: 18px;
|
||||
color: red;
|
||||
}
|
||||
.goods-item {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 16px;
|
||||
}
|
||||
.count-price {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.flowPrice {
|
||||
font-size: 24px;
|
||||
color: red;
|
||||
}
|
||||
.goods-title {
|
||||
margin: 0 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.label-item {
|
||||
margin: 10px 0;
|
||||
width: 20%;
|
||||
padding: 8px;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
> span {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
224
seller/src/views/statistics/order/orderStatistics.vue
Normal file
224
seller/src/views/statistics/order/orderStatistics.vue
Normal file
@@ -0,0 +1,224 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Row>
|
||||
<Col>
|
||||
<Card>
|
||||
<Form
|
||||
label-position="left"
|
||||
ref="searchForm"
|
||||
:model="params"
|
||||
inline
|
||||
:label-width="100"
|
||||
>
|
||||
<Form-item label="选择时间类型" prop="sn">
|
||||
<Select v-model="params.timeType" style="width: 200px">
|
||||
<Option
|
||||
v-for="item in typeList"
|
||||
:value="item.value"
|
||||
:key="item.value"
|
||||
>{{ item.label }}
|
||||
</Option
|
||||
>
|
||||
</Select>
|
||||
</Form-item>
|
||||
<Form-item label="按年查询" prop="year">
|
||||
<DatePicker
|
||||
type="year"
|
||||
style="width: 200px"
|
||||
v-model="year"
|
||||
@on-change="changeYear"
|
||||
></DatePicker>
|
||||
</Form-item>
|
||||
<Form-item label="按月查询" v-if="params.timeType == 'MONTH'">
|
||||
<InputNumber :max="12" :min="1" v-model="params.month"></InputNumber>
|
||||
</Form-item>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
<Card style="margin-top: 2px;height: 130px">
|
||||
<h3>订单统计</h3>
|
||||
<div class="ant-row">
|
||||
<div class="ant-col-4">
|
||||
<p class="static-menu">
|
||||
<span style="font-size: 14px;">总数</span>
|
||||
</p>
|
||||
<p class="static-num">
|
||||
{{priceData.totalNum}}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="static-menu">
|
||||
<span style="font-size: 14px;">总金额</span>
|
||||
</p>
|
||||
<p class="static-num">
|
||||
{{ priceData.price | unitPrice }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
|
||||
<Card style="margin-top: 2px">
|
||||
<Row>
|
||||
<Table :loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data" ref="table"
|
||||
sortable="custom"
|
||||
@on-sort-change="changeSort"
|
||||
@on-selection-change="changeSelect">
|
||||
|
||||
</Table>
|
||||
</Row>
|
||||
<Row type="flex" justify="end" class="page">
|
||||
<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
|
||||
how-sizer></Page>
|
||||
</Row>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Statistics from "@/api/statistics";
|
||||
|
||||
export default {
|
||||
name: "goodsStatistics",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
searchForm: [],
|
||||
params: {
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10, // 页面大小
|
||||
type: "NUM",
|
||||
timeType: "YEAR",
|
||||
year:'',
|
||||
},
|
||||
year:'',
|
||||
|
||||
priceData:{
|
||||
totalNum:0,
|
||||
price:0
|
||||
},
|
||||
loading: true, // 表单加载状态
|
||||
typeList: [
|
||||
{
|
||||
value: "YEAR",
|
||||
label: "年",
|
||||
},
|
||||
{
|
||||
value: "MONTH",
|
||||
label: "月",
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
title: "店铺",
|
||||
key: "sellerName",
|
||||
},
|
||||
{
|
||||
title: "订单编号",
|
||||
key: "orderItemSn",
|
||||
},
|
||||
{
|
||||
title: "购买人",
|
||||
key: "memberName",
|
||||
},
|
||||
{
|
||||
title: "订单金额",
|
||||
key: "finalPrice",
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
key: "createTime",
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
total: 0 // 表单数据总数
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
params: {
|
||||
handler(val) {
|
||||
this.init();
|
||||
},
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//初始化
|
||||
init() {
|
||||
this.getDataPage()
|
||||
},
|
||||
getDataPage() {
|
||||
this.loading = true;
|
||||
API_Statistics.getOrderStatistics(this.params).then((res) => {
|
||||
this.loading = false;
|
||||
this.data = res.result.records
|
||||
this.total = res.result.total
|
||||
});
|
||||
API_Statistics.getOrderStatisticsPrice(this.params).then((res) => {
|
||||
this.loading = false;
|
||||
this.priceData.totalNum = res.result.num
|
||||
this.priceData.price = res.result.price?res.result.price:0
|
||||
});
|
||||
},
|
||||
changeYear(item){
|
||||
this.params.year = item;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let nowDate = new Date();
|
||||
this.params.year = this.year = nowDate.getFullYear() + ''
|
||||
this.init();
|
||||
},
|
||||
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 建议引入通用样式 可删除下面样式代码
|
||||
@import "@/styles/table-common.scss";
|
||||
|
||||
.ant-row {
|
||||
position: relative;
|
||||
height: auto;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
zoom: 1;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
margin-left: 30px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
.ant-col-4 {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 11%;
|
||||
flex: 0 0 auto;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.static-num {
|
||||
color: rgb(51, 51, 51);
|
||||
font-size: 16px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.static-menu {
|
||||
color: rgb(51, 51, 51);
|
||||
font-size: 16px;
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
170
seller/src/views/statistics/order/refundOrder.vue
Normal file
170
seller/src/views/statistics/order/refundOrder.vue
Normal file
@@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
|
||||
<div class="shop">
|
||||
<h3>售后详情</h3>
|
||||
<div class="shop-item">
|
||||
<div class="label-item">
|
||||
<span>售后类型</span>
|
||||
<span>{{serviceTypeList[res.serviceType]}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>售后单状态</span>
|
||||
<span>{{serviceStatusList[res.serviceStatus]}}</span>
|
||||
</div>
|
||||
|
||||
<div class="label-item">
|
||||
<span>退款时间</span>
|
||||
<span>{{res.refundTime || '暂无'}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>申请退款金额</span>
|
||||
<span>{{res.applyRefundPrice || '0'}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>商家备注</span>
|
||||
<span>{{res.auditRemark || '暂无'}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>申请原因</span>
|
||||
<span>{{res.reason || '暂无'}}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="shop-item">
|
||||
<div class="label-item">
|
||||
<span>用户名</span>
|
||||
<span>{{res.memberName}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>店铺名称</span>
|
||||
<span>{{res.sellerName}}</span>
|
||||
</div>
|
||||
<div class="label-item">
|
||||
<span>创建时间</span>
|
||||
<span>{{res.createTime}}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<h3>商品详情</h3>
|
||||
<div class="shop-item">
|
||||
|
||||
<div class="goods-item">
|
||||
<div class="goods-img">
|
||||
<img class="img" :src="res.goodsImage" alt="">
|
||||
</div>
|
||||
<div class="goods-title">
|
||||
<div>{{res.goodsName}}</div>
|
||||
<div>{{'x'+res.num}}</div>
|
||||
<div class="goods-price">{{res.flowPrice | unitPrice('¥')}}</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="count-price">
|
||||
<div class="label-item">
|
||||
<span>实际退款金额</span>
|
||||
<span class="flowPrice">{{res.flowPrice | unitPrice('¥')}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
orderStatusList: {
|
||||
UNDELIVERED: "待发货",
|
||||
UNPAID: "未付款",
|
||||
PAID: "已付款",
|
||||
DELIVERED: "已发货",
|
||||
CANCELLED: "已取消",
|
||||
COMPLETED: "已完成",
|
||||
TAKE: "已完成",
|
||||
},
|
||||
// 售后类型
|
||||
serviceTypeList: {
|
||||
CANCEL: "取消",
|
||||
RETURN_GOODS: "退货",
|
||||
EXCHANGE_GOODS: "换货",
|
||||
RETURN_MONEY: "退款",
|
||||
},
|
||||
serviceStatusList: {
|
||||
APPLY: "申请售后",
|
||||
PASS: "通过售后",
|
||||
REFUSE: "拒绝售后",
|
||||
BUYER_RETURN: "买家退货,待卖家收货",
|
||||
SELLER_RE_DELIVERY: "商家换货/补发",
|
||||
SELLER_CONFIRM: "卖家确认收货",
|
||||
SELLER_TERMINATION: "卖家终止售后",
|
||||
BUYER_CONFIRM: "买家确认收货",
|
||||
BUYER_CANCEL: "买家取消售后",
|
||||
WAIT_REFUND: "等待平台退款",
|
||||
COMPLETE: "完成售后",
|
||||
},
|
||||
};
|
||||
},
|
||||
props: ["res"],
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
}
|
||||
.shop {
|
||||
padding: 10px 0;
|
||||
background: #fff;
|
||||
}
|
||||
.shop-item {
|
||||
display: flex;
|
||||
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
h3 {
|
||||
margin: 20px 16px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.goods-price {
|
||||
font-size: 18px;
|
||||
color: red;
|
||||
}
|
||||
.goods-item {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 16px;
|
||||
}
|
||||
.count-price {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.flowPrice {
|
||||
font-size: 24px;
|
||||
color: red;
|
||||
}
|
||||
.goods-title {
|
||||
margin: 0 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.label-item {
|
||||
margin: 10px 0;
|
||||
width: 20%;
|
||||
padding: 8px;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
> span {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
248
seller/src/views/statistics/traffic.vue
Normal file
248
seller/src/views/statistics/traffic.vue
Normal file
@@ -0,0 +1,248 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<Affix :offset-top="100">
|
||||
<Card class="card fixed-bottom">
|
||||
<affixTime @selected="clickBreadcrumb" />
|
||||
|
||||
</Card>
|
||||
</Affix>
|
||||
<Card class="card">
|
||||
<div>
|
||||
<h4>流量概况</h4>
|
||||
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-item">
|
||||
<div>
|
||||
访客数UV
|
||||
</div>
|
||||
<div>
|
||||
{{uvs||0}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box-item">
|
||||
<div>
|
||||
浏览量PV
|
||||
</div>
|
||||
<div>
|
||||
{{pvs||0}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</Card>
|
||||
|
||||
<Card class="card">
|
||||
<div>
|
||||
<h4>流量趋势</h4>
|
||||
<div id="orderChart"></div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card class="card">
|
||||
<div>
|
||||
<h4>客户增长报表</h4>
|
||||
<Table class="table" stripe :columns="columns" :data="data"></Table>
|
||||
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import affixTime from "@/views/lili-components/affix-time";
|
||||
import * as API_Member from "@/api/member";
|
||||
import { Chart } from "@antv/g2";
|
||||
import Cookies from "js-cookie";
|
||||
export default {
|
||||
components: { affixTime },
|
||||
|
||||
data() {
|
||||
return {
|
||||
// 时间
|
||||
|
||||
uvs: "", // 访客数
|
||||
pvs: "", // 浏览量
|
||||
|
||||
dateList: [ // 日期选择列表
|
||||
{
|
||||
title: "今天",
|
||||
selected: false,
|
||||
value: "TODAY",
|
||||
},
|
||||
{
|
||||
title: "昨天",
|
||||
selected: false,
|
||||
value: "YESTERDAY",
|
||||
},
|
||||
{
|
||||
title: "最近7天",
|
||||
selected: true,
|
||||
value: "LAST_SEVEN",
|
||||
},
|
||||
{
|
||||
title: "最近30天",
|
||||
selected: false,
|
||||
value: "LAST_THIRTY",
|
||||
},
|
||||
],
|
||||
|
||||
orderChart: "", // 流量趋势数据
|
||||
params: {
|
||||
searchType: "LAST_SEVEN",
|
||||
year: "",
|
||||
month: "",
|
||||
storeId: JSON.parse(Cookies.get("userInfo")).id || "",
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
key: "date",
|
||||
title: "日期",
|
||||
},
|
||||
{
|
||||
key: "pvNum",
|
||||
title: "浏览量",
|
||||
},
|
||||
{
|
||||
key: "uvNum",
|
||||
title: "访客数",
|
||||
},
|
||||
],
|
||||
|
||||
data: [], // 客户增长报表数据
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
params: {
|
||||
handler(val) {
|
||||
this.init();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 订单图
|
||||
initChart() {
|
||||
// 默认已经加载 legend-filter 交互
|
||||
/**
|
||||
* 将数据分成三组来进行展示
|
||||
*/
|
||||
|
||||
let uv = [];
|
||||
let pv = [];
|
||||
|
||||
this.data.forEach((item) => {
|
||||
uv.push({
|
||||
date: item.date,
|
||||
uvNum: item.uvNum,
|
||||
title: "访客数UV",
|
||||
pv: item.uvNum,
|
||||
});
|
||||
pv.push({
|
||||
date: item.date,
|
||||
pvNum: item.pvNum,
|
||||
pv: item.pvNum,
|
||||
title: "浏览量PV",
|
||||
});
|
||||
});
|
||||
|
||||
let data = [...uv, ...pv];
|
||||
|
||||
this.orderChart.data(data);
|
||||
this.orderChart.scale({
|
||||
activeQuantity: {
|
||||
range: [0, 1],
|
||||
nice: true,
|
||||
},
|
||||
});
|
||||
this.orderChart.tooltip({
|
||||
showCrosshairs: true,
|
||||
shared: true,
|
||||
});
|
||||
|
||||
this.orderChart
|
||||
.line()
|
||||
.position("date*pv")
|
||||
.color("title")
|
||||
.label("pv")
|
||||
.shape("smooth");
|
||||
|
||||
this.orderChart
|
||||
.point()
|
||||
.position("date*pv")
|
||||
.color("title")
|
||||
.label("pv")
|
||||
.shape("circle")
|
||||
.style({
|
||||
stroke: "#fff",
|
||||
lineWidth: 1,
|
||||
});
|
||||
|
||||
this.orderChart.render();
|
||||
},
|
||||
|
||||
clickBreadcrumb(item, index) {
|
||||
let callback = JSON.parse(JSON.stringify(item));
|
||||
|
||||
this.params = callback;
|
||||
},
|
||||
|
||||
init() {
|
||||
API_Member.getStatisticsList(this.params).then((res) => {
|
||||
if (res.result) {
|
||||
this.data = res.result;
|
||||
res.result.forEach((item) => {
|
||||
this.uvs += item.uvNum;
|
||||
this.pvs += item.pvNum;
|
||||
});
|
||||
|
||||
if (!this.orderChart) {
|
||||
this.orderChart = new Chart({
|
||||
container: "orderChart",
|
||||
autoFit: true,
|
||||
height: 500,
|
||||
padding: [70, 35, 70, 35],
|
||||
});
|
||||
}
|
||||
this.initChart();
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.table {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.wrapper {
|
||||
padding-bottom: 200px;
|
||||
}
|
||||
.box-item {
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
width: 25%;
|
||||
font-weight: bold;
|
||||
// align-items: center;
|
||||
justify-content: center;
|
||||
> div {
|
||||
margin: 4px;
|
||||
}
|
||||
}
|
||||
.box {
|
||||
background: rgb(250, 250, 250);
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
}
|
||||
.card {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user