mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-08-06 19:07:25 +08:00
manager 升级到vue3
This commit is contained in:
@@ -1,97 +1,85 @@
|
||||
<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>
|
||||
<span
|
||||
v-for="(item, index) in dateList"
|
||||
:key="index"
|
||||
:class="{ active: item.selected }"
|
||||
@click="clickBreadcrumb(item)"
|
||||
>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<div class="date-picker">
|
||||
<Select @on-change="changeSelect($event, selectedWay)" :value="month" placeholder="年月查询" clearable
|
||||
style="width:200px;margin-left:10px;">
|
||||
<Option v-for="(item, i) in dates" :value="item.year + '-' + item.month" :key="i" clearable>
|
||||
{{ item.year + '年' + item.month + '月' }}</Option>
|
||||
</Select>
|
||||
<el-select
|
||||
v-model="month"
|
||||
placeholder="年月查询"
|
||||
clearable
|
||||
style="width: 200px; margin-left: 10px"
|
||||
@change="changeSelect"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, i) in dates"
|
||||
:key="i"
|
||||
:label="item.year + '年' + item.month + '月'"
|
||||
:value="item.year + '-' + item.month"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="shop-list" v-if="!closeShop">
|
||||
<Select clearable @on-change="changeshop(selectedWay)" v-model="storeId" placeholder="店铺查询"
|
||||
style="width:200px;margin-left:10px;">
|
||||
<Scroll :on-reach-bottom="handleReachBottom">
|
||||
<Option v-for="(item, index) in shopsData" :value="item.id" :key="index">{{ item.storeName }}</Option>
|
||||
</Scroll>
|
||||
</Select>
|
||||
<div v-if="!closeShop" class="shop-list">
|
||||
<el-select
|
||||
v-model="storeId"
|
||||
placeholder="店铺查询"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 200px; margin-left: 10px"
|
||||
@change="changeshop"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in shopsData"
|
||||
:key="index"
|
||||
:label="item.storeName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getShopListData } from "@/api/shops.js";
|
||||
|
||||
export default {
|
||||
props: ["closeShop"],
|
||||
data() {
|
||||
return {
|
||||
month: "", // 月份
|
||||
|
||||
month: "",
|
||||
selectedWay: {
|
||||
// 可选时间项
|
||||
title: "过去7天",
|
||||
selected: true,
|
||||
searchType: "LAST_SEVEN",
|
||||
},
|
||||
storeId: "", // 店铺id
|
||||
dates: [], // 日期列表
|
||||
storeId: "",
|
||||
dates: [],
|
||||
params: {
|
||||
// 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
pageSize: 100,
|
||||
storeName: "",
|
||||
},
|
||||
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",
|
||||
},
|
||||
{ title: "今天", selected: false, searchType: "TODAY" },
|
||||
{ title: "昨天", selected: false, searchType: "YESTERDAY" },
|
||||
{ title: "过去7天", selected: true, searchType: "LAST_SEVEN" },
|
||||
{ title: "过去30天", selected: false, searchType: "LAST_THIRTY" },
|
||||
],
|
||||
originDateList: [
|
||||
// 筛选条件
|
||||
{
|
||||
title: "今天",
|
||||
selected: false,
|
||||
searchType: "TODAY",
|
||||
},
|
||||
{
|
||||
title: "昨天",
|
||||
selected: false,
|
||||
searchType: "YESTERDAY",
|
||||
},
|
||||
{
|
||||
title: "过去7天",
|
||||
selected: true,
|
||||
searchType: "LAST_SEVEN",
|
||||
},
|
||||
{
|
||||
title: "过去30天",
|
||||
selected: false,
|
||||
searchType: "LAST_THIRTY",
|
||||
},
|
||||
{ title: "今天", selected: false, searchType: "TODAY" },
|
||||
{ title: "昨天", selected: false, searchType: "YESTERDAY" },
|
||||
{ title: "过去7天", selected: true, searchType: "LAST_SEVEN" },
|
||||
{ title: "过去30天", selected: false, searchType: "LAST_THIRTY" },
|
||||
],
|
||||
|
||||
shopTotal: "", // 店铺总数
|
||||
shopsData: [], // 店铺数据
|
||||
shopTotal: 0,
|
||||
shopsData: [],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@@ -99,58 +87,35 @@ export default {
|
||||
this.getShopList();
|
||||
},
|
||||
methods: {
|
||||
// 页面触底
|
||||
handleReachBottom() {
|
||||
setTimeout(() => {
|
||||
if (this.params.pageNumber * this.params.pageSize <= this.shopTotal) {
|
||||
this.params.pageNumber++;
|
||||
this.getShopList();
|
||||
}
|
||||
}, 1500);
|
||||
},
|
||||
// 查询店铺列表
|
||||
getShopList() {
|
||||
getShopListData(this.params).then((res) => {
|
||||
if (res.success) {
|
||||
/**
|
||||
* 解决数据请求中,滚动栏会一直上下跳动
|
||||
*/
|
||||
this.shopTotal = res.result.total;
|
||||
|
||||
this.shopsData.push(...res.result.records);
|
||||
this.shopsData = res.result.records || [];
|
||||
}
|
||||
});
|
||||
},
|
||||
// 变更店铺
|
||||
changeshop(val) {
|
||||
changeshop() {
|
||||
this.selectedWay.storeId = this.storeId;
|
||||
this.$emit("selected", this.selectedWay);
|
||||
},
|
||||
|
||||
// 获取近5年 年月
|
||||
getFiveYears() {
|
||||
let getYear = new Date().getFullYear();
|
||||
|
||||
let lastFiveYear = getYear - 5;
|
||||
let maxMonth = new Date().getMonth() + 1;
|
||||
let dates = [];
|
||||
// 循环出过去5年
|
||||
const getYear = new Date().getFullYear();
|
||||
const lastFiveYear = getYear - 5;
|
||||
const maxMonth = new Date().getMonth() + 1;
|
||||
const dates = [];
|
||||
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,
|
||||
});
|
||||
if (year === getYear && month > maxMonth) {
|
||||
continue;
|
||||
}
|
||||
dates.push({ year, month });
|
||||
}
|
||||
}
|
||||
this.dates = dates.reverse();
|
||||
},
|
||||
// 改变已选店铺
|
||||
changeSelect(e) {
|
||||
this.month = e
|
||||
this.month = e;
|
||||
if (this.month) {
|
||||
this.dateList.forEach((res) => {
|
||||
res.selected = false;
|
||||
@@ -158,53 +123,44 @@ export default {
|
||||
this.selectedWay.year = this.month.split("-")[0];
|
||||
this.selectedWay.month = this.month.split("-")[1];
|
||||
this.selectedWay.searchType = "";
|
||||
|
||||
this.$emit("selected", this.selectedWay);
|
||||
} else {
|
||||
|
||||
const current = this.dateList.find(item => { return item.selected })
|
||||
this.selectedWay = current
|
||||
this.clickBreadcrumb(current)
|
||||
const current = this.dateList.find((item) => item.selected);
|
||||
this.selectedWay = current;
|
||||
this.clickBreadcrumb(current);
|
||||
this.$emit("selected", this.selectedWay);
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
// 变更时间
|
||||
clickBreadcrumb(item) {
|
||||
|
||||
let currentIndex;
|
||||
this.dateList.forEach((res,index) => {
|
||||
this.dateList.forEach((res, index) => {
|
||||
res.selected = false;
|
||||
if(res.title === item.title){
|
||||
currentIndex = index
|
||||
if (res.title === item.title) {
|
||||
currentIndex = index;
|
||||
}
|
||||
});
|
||||
item.selected = true;
|
||||
item.storeId = this.storeId;
|
||||
this.month = "";
|
||||
if (item.searchType == "") {
|
||||
let currentDate = this.originDateList[currentIndex].searchType
|
||||
if (currentDate) {
|
||||
item.searchType = currentDate
|
||||
} else {
|
||||
item.searchType = "LAST_SEVEN";
|
||||
}
|
||||
if (item.searchType === "") {
|
||||
const currentDate = this.originDateList[currentIndex].searchType;
|
||||
item.searchType = currentDate || "LAST_SEVEN";
|
||||
}
|
||||
this.selectedWay = item;
|
||||
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 {
|
||||
|
||||
> span {
|
||||
margin-right: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -215,8 +171,6 @@ export default {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.date-picker {}
|
||||
|
||||
.active:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
|
||||
@@ -122,7 +122,7 @@ export default {
|
||||
deactivated() {
|
||||
this.destroyTinymce();
|
||||
},
|
||||
destroyed() {
|
||||
unmounted() {
|
||||
this.destroyTinymce();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const plugins = [
|
||||
'advlist', 'anchor', 'autolink', 'autosave', 'code', 'codesample', 'directionality', 'emoticons', 'fullscreen', 'image', 'importcss', 'insertdatetime', 'link', 'lists', 'media', 'nonbreaking', 'pagebreak', 'preview', 'save', 'searchreplace', 'table', 'template', 'visualblocks', 'visualchars', 'wordcount'
|
||||
'advlist', 'anchor', 'autolink', 'autosave', 'code', 'codesample', 'directionality', 'emoticons', 'fullscreen', 'image', 'importcss', 'insertdatetime', 'link', 'lists', 'media', 'nonbreaking', 'pagebreak', 'preview', 'save', 'searchreplace', 'table', 'visualblocks', 'visualchars', 'wordcount'
|
||||
]
|
||||
export default plugins
|
||||
|
||||
@@ -1,70 +1,90 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<Button @click="handleClickUploadImage">上传图片</Button>
|
||||
<Modal v-model="show" width="850" @on-ok="callback" title="上传图片">
|
||||
<div class="import-oss" @click="importOSS">
|
||||
从资源库中导入
|
||||
</div>
|
||||
<el-button @click="handleClickUploadImage">上传图片</el-button>
|
||||
<el-dialog v-model="show" width="850px" title="上传图片" append-to-body :z-index="3500">
|
||||
<div class="import-oss" @click="importOSS">从资源库中导入</div>
|
||||
<div style="display: flex; flex-wrap: wrap">
|
||||
<vuedraggable
|
||||
:animation="200"
|
||||
:list="images"
|
||||
>
|
||||
<vuedraggable :animation="200" :list="images">
|
||||
<div
|
||||
v-for="(item, __index) in images"
|
||||
:key="__index"
|
||||
class="upload-list"
|
||||
>
|
||||
<template>
|
||||
<img alt="image" :src="item.url"/>
|
||||
<div class="upload-list-cover">
|
||||
<div>
|
||||
<Icon
|
||||
size="30"
|
||||
type="md-search"
|
||||
@click.native="$previewImage(item.url)"
|
||||
></Icon>
|
||||
<Icon
|
||||
size="30"
|
||||
type="md-trash"
|
||||
@click.native="handleRemoveGoodsPicture(__index)"
|
||||
></Icon>
|
||||
</div>
|
||||
<img alt="image" :src="item.url" />
|
||||
<div class="upload-list-cover">
|
||||
<div>
|
||||
<el-icon class="action-icon" :size="30" @click="handleView(item.url)">
|
||||
<ZoomIn />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="action-icon"
|
||||
:size="30"
|
||||
@click="handleRemoveGoodsPicture(__index)"
|
||||
>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</vuedraggable>
|
||||
<div class="upload-box">
|
||||
<Upload
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:action="uploadFileUrl"
|
||||
:format="['jpg', 'jpeg', 'png']"
|
||||
:headers="{ ...accessToken }"
|
||||
:max-size="10240"
|
||||
:on-exceeded-size="handleMaxSize"
|
||||
:on-format-error="handleFormatError"
|
||||
:on-success="handleSuccessGoodsPicture"
|
||||
:show-upload-list="false"
|
||||
:headers="accessToken"
|
||||
:show-file-list="false"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
drag
|
||||
multiple
|
||||
type="drag"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-success="handleSuccessGoodsPicture"
|
||||
:on-error="handleUploadError"
|
||||
>
|
||||
<div style="width: 148px; height: 148px; line-height: 148px">
|
||||
<Icon size="20" type="md-add"></Icon>
|
||||
<div class="upload-trigger">
|
||||
<el-icon :size="20"><Plus /></el-icon>
|
||||
</div>
|
||||
</Upload>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<template #footer>
|
||||
<el-button @click="show = false">取消</el-button>
|
||||
<el-button type="primary" @click="callback">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<Modal width="1000" v-model="showOssManager" @on-ok="confirmUrls">
|
||||
<OssManage ref="ossManage" :isComponent="true" :initialize="showOssManager" @selected="(list)=>{ selectedImage = list}" @callback="handleCallback" />
|
||||
</Modal>
|
||||
<el-dialog
|
||||
v-model="showOssManager"
|
||||
width="1000px"
|
||||
append-to-body
|
||||
:z-index="3600"
|
||||
destroy-on-close
|
||||
@closed="confirmUrls"
|
||||
>
|
||||
<OssManage
|
||||
ref="ossManage"
|
||||
:is-component="true"
|
||||
:initialize="showOssManager"
|
||||
@selected="(list) => { selectedImage = list }"
|
||||
@callback="handleCallback"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="showOssManager = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmUrls">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="viewImage" title="图片预览" width="520px" append-to-body :z-index="3700">
|
||||
<img :src="previewUrl" alt="预览" style="width: 100%; display: block; margin: 0 auto" />
|
||||
<template #footer>
|
||||
<el-button @click="viewImage = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { Delete, Plus, ZoomIn } from "@element-plus/icons-vue";
|
||||
import vuedraggable from "vuedraggable";
|
||||
import {uploadFile} from "@/libs/axios";
|
||||
// import OssManage from "@/views/sys/oss-manage/ossManage";
|
||||
import { uploadFile } from "@/libs/axios";
|
||||
import OssManage from "@/views/sys/oss-manage/ossManage.vue";
|
||||
|
||||
export default {
|
||||
@@ -72,16 +92,21 @@ export default {
|
||||
components: {
|
||||
OssManage,
|
||||
vuedraggable,
|
||||
Delete,
|
||||
Plus,
|
||||
ZoomIn,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false, // 是否显示弹窗
|
||||
uploadFileUrl: uploadFile, // 上传地址
|
||||
accessToken:"",
|
||||
showOssManager:false, // 是否显示oss管理弹窗
|
||||
images:[],
|
||||
selectedImage:[]
|
||||
}
|
||||
show: false,
|
||||
uploadFileUrl: uploadFile,
|
||||
accessToken: {},
|
||||
showOssManager: false,
|
||||
images: [],
|
||||
selectedImage: [],
|
||||
viewImage: false,
|
||||
previewUrl: "",
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.accessToken = {
|
||||
@@ -89,71 +114,73 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClickUploadImage(){
|
||||
handleClickUploadImage() {
|
||||
this.show = true;
|
||||
},
|
||||
// 回调给父级
|
||||
callback() {
|
||||
// 先给数据做一下处理 然后将数据传给父级
|
||||
const formatImages = this.images.map((item) => item.url);
|
||||
this.$emit('callback',formatImages)
|
||||
handleView(url) {
|
||||
this.previewUrl = url;
|
||||
this.viewImage = true;
|
||||
},
|
||||
callback() {
|
||||
const formatImages = this.images.map((item) => item.url);
|
||||
this.$emit("callback", formatImages);
|
||||
this.show = false;
|
||||
},
|
||||
// 移除商品图片
|
||||
handleRemoveGoodsPicture(__index) {
|
||||
this.images.splice(__index, 1);
|
||||
},
|
||||
// 图片大小不正确
|
||||
handleMaxSize(file) {
|
||||
this.$Notice.warning({
|
||||
title: "超过文件大小限制",
|
||||
desc: "图片大小不能超过10MB",
|
||||
});
|
||||
handleBeforeUpload(file) {
|
||||
const okType = ["image/jpeg", "image/png", "image/jpg"].includes(file.type);
|
||||
if (!okType) {
|
||||
this.$Message.warning("文件 " + file.name + " 的格式不正确,请选择 jpg/jpeg/png");
|
||||
return false;
|
||||
}
|
||||
if (file.size / 1024 / 1024 > 10) {
|
||||
this.$Message.warning("图片大小不能超过10MB");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 图片格式不正确
|
||||
handleFormatError(file) {
|
||||
this.$Notice.warning({
|
||||
title: "文件格式不正确",
|
||||
desc: "文件 " + file.name + " 的格式不正确",
|
||||
});
|
||||
},
|
||||
// sku图片上传成功
|
||||
handleSuccessGoodsPicture(res, file) {
|
||||
if (file.response) {
|
||||
file.url = file.response.result;
|
||||
this.images.push(file);
|
||||
handleSuccessGoodsPicture(res) {
|
||||
const url = res?.result ?? res?.data?.result;
|
||||
if (url) {
|
||||
this.images.push({ url });
|
||||
} else {
|
||||
this.$Message.error(res?.message || "上传失败");
|
||||
}
|
||||
},
|
||||
confirmUrls(){
|
||||
// this.selectedImage.length ? this.selectedImage.forEach(element => {
|
||||
// this.images.push({ url: element.url })
|
||||
// }):''
|
||||
this.showOssManager = false
|
||||
handleUploadError(err) {
|
||||
this.$Message.error(err?.message || String(err));
|
||||
},
|
||||
handleCallback(val){
|
||||
this.$Message.success("导入成功")
|
||||
this.images.push({url:val.url})
|
||||
confirmUrls() {
|
||||
this.showOssManager = false;
|
||||
},
|
||||
// 从资源库中导入图片
|
||||
importOSS(){
|
||||
handleCallback(val) {
|
||||
this.$Message.success("导入成功");
|
||||
this.images.push({ url: val.url });
|
||||
},
|
||||
importOSS() {
|
||||
this.showOssManager = true;
|
||||
this.$refs.ossManage.selectImage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.ossManage) {
|
||||
this.$refs.ossManage.selectImage = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.import-oss{
|
||||
.import-oss {
|
||||
margin-bottom: 10px;
|
||||
text-align: right;
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
.wrapper{
|
||||
.wrapper {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.upload-list {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
@@ -166,47 +193,48 @@ export default {
|
||||
margin-right: 4px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.upload-box{
|
||||
.upload-box {
|
||||
margin: 10px 0;
|
||||
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.upload-trigger {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
line-height: 148px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.upload-list img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.upload-list-cover {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.upload-list:hover .upload-list-cover {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.upload-list-cover div {
|
||||
margin-top: 50px;
|
||||
width: 100%;
|
||||
|
||||
>i {
|
||||
width: 50%;
|
||||
margin-top: 8px;
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.action-icon {
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -51,49 +51,45 @@
|
||||
<li class="hz-u-square hz-u-square-br" data-pointer="dealBR"></li>
|
||||
</ul>
|
||||
|
||||
<Modal
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
title="编辑热区"
|
||||
draggable
|
||||
scrollable
|
||||
:mask="false"
|
||||
ok-text="保存"
|
||||
@on-ok="saveZone"
|
||||
@on-cancel="cancelZone"
|
||||
:modal="false"
|
||||
append-to-body
|
||||
width="520px"
|
||||
@close="cancelZone"
|
||||
>
|
||||
<div>
|
||||
<div class="hz-edit-img">
|
||||
<img class="show-image" :src="zoneForm.img" alt />
|
||||
</div>
|
||||
|
||||
<Form :model="zoneForm" :label-width="80">
|
||||
<!-- <FormItem label="图片链接:">
|
||||
<Input v-model="zoneForm.img"></Input>
|
||||
<Button size="small" type="primary" @click="handleSelectImg"
|
||||
>选择图片</Button
|
||||
<el-form :model="zoneForm" label-width="80px">
|
||||
<el-form-item label="跳转链接:">
|
||||
<el-input type="textarea" v-if="zoneForm.type === 'other' && zoneForm.title === '外部链接'" v-model="zoneForm.link" />
|
||||
<el-button size="small" type="primary" @click="handleSelectLink"
|
||||
>选择链接</el-button
|
||||
>
|
||||
:v-model="zoneForm.type === 'goods' ? zoneForm.goodsName : zoneForm.link"
|
||||
</FormItem> -->
|
||||
<FormItem label="跳转链接:">
|
||||
<Input type="textarea" v-if="zoneForm.type === 'other' && zoneForm.title === '外部链接'" v-model="zoneForm.link" ></Input>
|
||||
<Button size="small" type="primary" @click="handleSelectLink"
|
||||
>选择链接</Button
|
||||
>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</Modal>
|
||||
<template #footer>
|
||||
<el-button @click="cancelZone">取消</el-button>
|
||||
<el-button type="primary" @click="saveZone">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
<!-- 选择图片 -->
|
||||
<Modal width="1200px" v-model="picModelFlag" footer-hide>
|
||||
<el-dialog width="1200px" v-model="picModelFlag" append-to-body destroy-on-close>
|
||||
<ossManage
|
||||
@callback="callbackSelected"
|
||||
:isComponent="true"
|
||||
:initialize="picModelFlag"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</Modal>
|
||||
<template #footer />
|
||||
</el-dialog>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
@@ -179,7 +175,7 @@ export default {
|
||||
},
|
||||
// 已选链接
|
||||
selectedLink(val) {
|
||||
this.zoneForm.link = this.$options.filters.formatLinkType(val);
|
||||
this.zoneForm.link = this.$filters.formatLinkType(val);
|
||||
this.settingZone(val);
|
||||
this.changeInfo(this.zoneForm);
|
||||
},
|
||||
@@ -220,7 +216,10 @@ export default {
|
||||
break;
|
||||
}
|
||||
},
|
||||
saveZone() {},
|
||||
saveZone() {
|
||||
this.showModal = false;
|
||||
this.changeInfo(this.zoneForm);
|
||||
},
|
||||
cancelZone() {
|
||||
this.showModal = false;
|
||||
},
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<template>
|
||||
<Modal
|
||||
:styles="{ top: '120px' }"
|
||||
width="800"
|
||||
@on-cancel="clickClose"
|
||||
@on-ok="clickOK"
|
||||
<el-dialog
|
||||
v-model="flag"
|
||||
:mask-closable="false"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
title="绘制热区"
|
||||
scrollable
|
||||
top="120px"
|
||||
destroy-on-close
|
||||
@close="clickClose"
|
||||
>
|
||||
<template v-if="flag">
|
||||
<hotzone
|
||||
@@ -17,7 +16,11 @@
|
||||
:image="res.img"
|
||||
></hotzone>
|
||||
</template>
|
||||
</Modal>
|
||||
<template #footer>
|
||||
<el-button @click="clickClose">取消</el-button>
|
||||
<el-button type="primary" @click="clickOK">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import hotzone from "./components/Hotzone.vue";
|
||||
@@ -57,11 +60,11 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
::v-deep .ivu-modal {
|
||||
:deep(.el-dialog) {
|
||||
overflow: hidden;
|
||||
height: 650px !important;
|
||||
}
|
||||
::v-deep .ivu-modal-body {
|
||||
:deep(.el-dialog__body) {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -4,46 +4,26 @@
|
||||
<div class="query-wrapper">
|
||||
<div class="query-item">
|
||||
<div>搜索范围</div>
|
||||
<Input
|
||||
<el-input
|
||||
v-model="goodsParams.goodsName"
|
||||
placeholder="商品名称"
|
||||
@on-clear="
|
||||
goodsData = [];
|
||||
goodsParams.goodsName = '';
|
||||
goodsParams.pageNumber = 1;
|
||||
getQueryGoodsList();
|
||||
"
|
||||
@on-enter="
|
||||
() => {
|
||||
goodsData = [];
|
||||
goodsParams.pageNumber = 1;
|
||||
getQueryGoodsList();
|
||||
}
|
||||
"
|
||||
icon="ios-search"
|
||||
clearable
|
||||
style="width: 150px"
|
||||
v-model="goodsParams.goodsName"
|
||||
@clear="onSearchGoods"
|
||||
@keyup.enter="onSearchGoods"
|
||||
/>
|
||||
</div>
|
||||
<div class="query-item">
|
||||
<Cascader
|
||||
<el-cascader
|
||||
v-model="category"
|
||||
:options="skuList"
|
||||
placeholder="请选择商品分类"
|
||||
style="width: 250px"
|
||||
:data="skuList"
|
||||
></Cascader>
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<div class="query-item">
|
||||
<Button
|
||||
type="primary"
|
||||
@click="
|
||||
goodsData = [];
|
||||
goodsParams.pageNumber = 1;
|
||||
getQueryGoodsList();
|
||||
"
|
||||
icon="ios-search"
|
||||
>搜索</Button
|
||||
>
|
||||
<el-button type="primary" @click="onSearchGoods">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
@@ -63,27 +43,33 @@
|
||||
<div class="wap-content-desc">
|
||||
<div class="wap-content-desc-title">{{ item.goodsName }}</div>
|
||||
|
||||
<div class="wap-sku">{{ item.goodsUnit }}<Tag style="margin-left: 10px;" :color="item.salesModel === 'RETAIL' ? 'default' : 'geekblue'">{{item.salesModel === "RETAIL" ? "零售型" : "批发型"}}</Tag></div>
|
||||
<div class="wap-sku">
|
||||
{{ item.goodsUnit }}
|
||||
<el-tag
|
||||
style="margin-left: 10px"
|
||||
:type="item.salesModel === 'RETAIL' ? 'info' : 'primary'"
|
||||
>
|
||||
{{ item.salesModel === "RETAIL" ? "零售型" : "批发型" }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="wap-content-desc-bottom">
|
||||
<div>¥{{ item.price | unitPrice }}</div>
|
||||
<div>¥{{ $filters.unitPrice(item.price) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Spin size="large" fix v-if="loading"></Spin>
|
||||
<div v-if="loading" v-loading="loading" class="loading-mask" />
|
||||
|
||||
<div v-if="empty" class="empty">暂无商品信息</div>
|
||||
</div>
|
||||
<Page
|
||||
:total="total"
|
||||
<el-pagination
|
||||
v-model:current-page="goodsParams.pageNumber"
|
||||
class="pageration"
|
||||
@on-change="changePageSize"
|
||||
:total="total"
|
||||
:page-size="goodsParams.pageSize"
|
||||
layout="total, prev, pager, next"
|
||||
size="small"
|
||||
show-total
|
||||
show-elevator
|
||||
|
||||
>
|
||||
</Page>
|
||||
@current-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -145,6 +131,11 @@ export default {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
onSearchGoods() {
|
||||
this.goodsData = [];
|
||||
this.goodsParams.pageNumber = 1;
|
||||
this.getQueryGoodsList();
|
||||
},
|
||||
changePageSize(v){
|
||||
this.goodsParams.pageNumber = v;
|
||||
this.getQueryGoodsList();
|
||||
@@ -201,7 +192,6 @@ export default {
|
||||
arr[index] = {
|
||||
value: grandson.id,
|
||||
label: grandson.name,
|
||||
children: "",
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
<template>
|
||||
<Modal :styles="{ top: '120px' }" width="1160" :z-index="10000" @on-cancel="clickClose" @on-ok="clickOK" v-model="flag" :mask-closable="false" scrollable>
|
||||
<el-dialog
|
||||
v-model="flag"
|
||||
width="1160px"
|
||||
top="120px"
|
||||
:z-index="10000"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="clickClose"
|
||||
>
|
||||
<template v-if="flag">
|
||||
<goodsDialog
|
||||
@selected="
|
||||
@@ -21,7 +30,11 @@
|
||||
class="linkDialog"
|
||||
/>
|
||||
</template>
|
||||
</Modal>
|
||||
<template #footer>
|
||||
<el-button @click="clickClose">取消</el-button>
|
||||
<el-button type="primary" @click="clickOK">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import goodsDialog from "./goods-dialog";
|
||||
@@ -86,11 +99,7 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
::v-deep .ivu-modal {
|
||||
overflow: hidden;
|
||||
height: 650px !important;
|
||||
}
|
||||
::v-deep .ivu-modal-body {
|
||||
:deep(.el-dialog__body) {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<Tabs :value="wap[0].title" class="tabs">
|
||||
<TabPane
|
||||
<el-tabs v-model="activeTab" class="tabs">
|
||||
<el-tab-pane
|
||||
:label="item.title"
|
||||
:name="item.title"
|
||||
@click="clickTag(item, i)"
|
||||
v-for="(item, i) in wap"
|
||||
:key="i"
|
||||
>
|
||||
@@ -17,9 +16,8 @@
|
||||
}
|
||||
"
|
||||
/>
|
||||
</TabPane>
|
||||
<!-- </template> -->
|
||||
</Tabs>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -30,13 +28,16 @@ export default {
|
||||
components: {
|
||||
goodsDialog
|
||||
},
|
||||
setup() {
|
||||
return { templateWay };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
templateWay, // 模板数据
|
||||
changed: "", // 变更模板
|
||||
selected: 0, // 已选数据
|
||||
selectedLink: "", //选中的链接
|
||||
wap, // tab标签
|
||||
activeTab: wap[0]?.title || "",
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -122,13 +123,8 @@ export default {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep .ivu-modal {
|
||||
overflow: hidden;
|
||||
height: 650px !important;
|
||||
}
|
||||
::v-deep .ivu-modal-body {
|
||||
width: 100%;
|
||||
:deep(.el-tabs__content) {
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -42,12 +42,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .ivu-scroll-container {
|
||||
:deep(.ivu-scroll-container){
|
||||
width: 100% !important;
|
||||
height: 400px !important;
|
||||
}
|
||||
|
||||
::v-deep .ivu-scroll-content {
|
||||
:deep(.ivu-scroll-content){
|
||||
/* */
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -81,7 +81,7 @@
|
||||
align-items: center;
|
||||
margin: 10px;
|
||||
|
||||
::v-deep img {
|
||||
:deep(img){
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
text-align: center;
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { markRaw } from "vue";
|
||||
import category from "./category.vue";
|
||||
import shops from "./shops.vue";
|
||||
import marketing from "./marketing.vue";
|
||||
import pages from "./pages.vue";
|
||||
import goods from "../goods-dialog.vue";
|
||||
import other from "./other.vue";
|
||||
import special from "./special.vue";
|
||||
|
||||
import category from './category.vue'
|
||||
import shops from './shops.vue'
|
||||
import marketing from './marketing.vue'
|
||||
import pages from './pages.vue'
|
||||
import goods from '../goods-dialog.vue'
|
||||
import other from './other.vue'
|
||||
import special from './special.vue'
|
||||
export default {
|
||||
pages,
|
||||
marketing,
|
||||
shops,
|
||||
category,
|
||||
goods,
|
||||
other,
|
||||
special
|
||||
}
|
||||
pages: markRaw(pages),
|
||||
marketing: markRaw(marketing),
|
||||
shops: markRaw(shops),
|
||||
category: markRaw(category),
|
||||
goods: markRaw(goods),
|
||||
other: markRaw(other),
|
||||
special: markRaw(special),
|
||||
};
|
||||
|
||||
@@ -2,49 +2,66 @@
|
||||
<div class="wrapper">
|
||||
<div class="list">
|
||||
<div
|
||||
class="list-item"
|
||||
v-for="(item, index) in Object.keys(promotionList)"
|
||||
:key="index"
|
||||
@click="clickPromotion(item, index)"
|
||||
class="list-item"
|
||||
:class="{ active: selectedIndex == index }"
|
||||
@click="clickPromotion(item, index)"
|
||||
>
|
||||
{{ typeOption(item).title }}
|
||||
</div>
|
||||
|
||||
<!-- <div class="list-item" >暂无活动</div> -->
|
||||
</div>
|
||||
<div class="content">
|
||||
<div v-if="showPromotionList">
|
||||
<!-- <div class="search-views">
|
||||
<Input v-model="value11" disabled class="search">
|
||||
<span slot="prepend">店铺名称</span>
|
||||
</Input>
|
||||
<Button type="primary">选择</Button>
|
||||
|
||||
</div> -->
|
||||
|
||||
<div class="tables">
|
||||
<Table
|
||||
height="350"
|
||||
border
|
||||
tooltip
|
||||
:loading="loading"
|
||||
:columns="activeColumns"
|
||||
:data="showPromotionList"
|
||||
></Table>
|
||||
<el-table v-loading="loading" border height="350" :data="showPromotionList" style="width: 100%">
|
||||
<template v-if="isSeckillMode">
|
||||
<el-table-column prop="goodsName" label="商品名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="storeName" label="店铺名称" show-overflow-tooltip />
|
||||
<el-table-column label="活动时间" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ row.timeLine }}点</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="原价" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ $filters.unitPrice(row.originalPrice) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="现价" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ $filters.unitPrice(row.price, "¥") }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ seckillStatusText(row.promotionApplyStatus) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-table-column prop="goodsName" label="商品名称" show-overflow-tooltip />
|
||||
<el-table-column prop="storeName" label="店铺名称" show-overflow-tooltip />
|
||||
<el-table-column prop="startTime" label="开始时间" show-overflow-tooltip />
|
||||
<el-table-column prop="endTime" label="结束时间" show-overflow-tooltip />
|
||||
</template>
|
||||
<el-table-column label="操作" width="100" fixed="right" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<a v-if="row" class="link-text" @click="selectedPromotion({ row, index: $index })">
|
||||
{{ index === $index ? "已选" : "选择" }}
|
||||
</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<Page
|
||||
@on-change="
|
||||
(val) => {
|
||||
params.pageNumber = val;
|
||||
}
|
||||
"
|
||||
:current="params.pageNumber"
|
||||
:page-size="params.pageSize"
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
class="mt_10"
|
||||
:total="Number(totals)"
|
||||
layout="prev, pager, next, jumper"
|
||||
size="small"
|
||||
show-elevator
|
||||
@current-change="(val) => { params.pageNumber = val; }"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,225 +69,29 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getAllPromotion,
|
||||
getPromotionSeckill,
|
||||
getPromotionGoods,
|
||||
} from "@/api/promotion";
|
||||
import { getAllPromotion } from "@/api/promotion";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
totals: "", // 总数
|
||||
loading: true, //表格请求数据为true
|
||||
promotionList: "", // 活动列表
|
||||
selectedIndex: 0, //左侧菜单选择
|
||||
promotions: "", //选中的活动key
|
||||
index: 999, // 已选下标
|
||||
totals: "",
|
||||
loading: true,
|
||||
promotionList: "",
|
||||
selectedIndex: 0,
|
||||
promotions: "",
|
||||
index: 999,
|
||||
params: {
|
||||
// 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
},
|
||||
pintuanColumns: [
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "店铺名称",
|
||||
key: "storeName",
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "开始时间",
|
||||
key: "startTime",
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "结束时间",
|
||||
key: "endTime",
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
fixed: "right",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"a",
|
||||
{
|
||||
style: {
|
||||
color: "#2d8cf0",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.selectedPromotion(params);
|
||||
},
|
||||
},
|
||||
},
|
||||
this.index == params.index ? "已选" : "选择"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
seckillColumns: [
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
tooltip: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: "店铺名称",
|
||||
key: "storeName",
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "活动时间",
|
||||
key: "timeLine",
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
return h("div", {}, `${params.row.timeLine}点`);
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "原价",
|
||||
key: "originalPrice",
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
{},
|
||||
this.$options.filters.unitPrice(params.row.originalPrice)
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "现价",
|
||||
key: "price",
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
{
|
||||
style: {},
|
||||
},
|
||||
this.$options.filters.unitPrice(params.row.price, "¥")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "promotionApplyStatus",
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
"div",
|
||||
{
|
||||
style: {},
|
||||
},
|
||||
params.row.promotionApplyStatus == "APPLY"
|
||||
? "申请"
|
||||
: params.row.promotionApplyStatus == "PASS"
|
||||
? "通过"
|
||||
: "拒绝"
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
width: 100,
|
||||
fixed: "right",
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"a",
|
||||
{
|
||||
style: {
|
||||
color: "#2d8cf0",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.selectedPromotion(params);
|
||||
},
|
||||
},
|
||||
},
|
||||
this.index == params.index ? "已选" : "选择"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
activeColumns: [], // 活动表头
|
||||
|
||||
columns: [
|
||||
{
|
||||
title: "活动标题",
|
||||
key: "title",
|
||||
tooltip: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: "商品名称",
|
||||
key: "goodsName",
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "活动开始时间",
|
||||
key: "startTime",
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "活动结束时间",
|
||||
key: "endTime",
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
fixed: "right",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"a",
|
||||
{
|
||||
style: {
|
||||
color: "#2d8cf0",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.selectedPromotion(params);
|
||||
},
|
||||
},
|
||||
},
|
||||
this.index == params.index ? "已选" : "选择"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
promotionData: "", //商品集合
|
||||
|
||||
showPromotionList: [], //显示当前促销的商品
|
||||
showPromotionList: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isSeckillMode() {
|
||||
return this.promotions === "SECKILL";
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
@@ -278,97 +99,48 @@ export default {
|
||||
params: {
|
||||
handler() {
|
||||
this.index = 999;
|
||||
this.typeOption(this.promotions) &&
|
||||
this.typeOption(this.promotions).methodsed();
|
||||
this.typeOption(this.promotions) && this.typeOption(this.promotions).methodsed();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
seckillStatusText(v) {
|
||||
if (v === "APPLY") return "申请";
|
||||
if (v === "PASS") return "通过";
|
||||
return "拒绝";
|
||||
},
|
||||
sortGoods(type) {
|
||||
this.loading = false;
|
||||
this.params.pageNumber - 1;
|
||||
this.showPromotionList = this.promotionList[type];
|
||||
},
|
||||
typeOption(type) {
|
||||
// 活动选项
|
||||
switch (type) {
|
||||
case "FULL_DISCOUNT":
|
||||
return {
|
||||
title: "满减",
|
||||
methodsed: () => {
|
||||
this.showPromotionList = [];
|
||||
this.activeColumns = this.pintuanColumns;
|
||||
|
||||
this.sortGoods("FULL_DISCOUNT");
|
||||
},
|
||||
};
|
||||
return { title: "满减", methodsed: () => { this.showPromotionList = []; this.sortGoods("FULL_DISCOUNT"); } };
|
||||
case "PINTUAN":
|
||||
return {
|
||||
title: "拼团",
|
||||
methodsed: (id) => {
|
||||
this.showPromotionList = [];
|
||||
this.activeColumns = this.pintuanColumns;
|
||||
this.sortGoods("PINTUAN");
|
||||
},
|
||||
};
|
||||
|
||||
return { title: "拼团", methodsed: () => { this.showPromotionList = []; this.sortGoods("PINTUAN"); } };
|
||||
case "KANJIA":
|
||||
return {
|
||||
title: "砍价",
|
||||
methodsed: (id) => {
|
||||
this.showPromotionList = [];
|
||||
this.activeColumns = this.pintuanColumns;
|
||||
this.sortGoods("KANJIA");
|
||||
},
|
||||
};
|
||||
return { title: "砍价", methodsed: () => { this.showPromotionList = []; this.sortGoods("KANJIA"); } };
|
||||
case "SECKILL":
|
||||
return {
|
||||
title: "秒杀",
|
||||
methodsed: () => {
|
||||
this.showPromotionList = [];
|
||||
this.activeColumns = this.seckillColumns;
|
||||
this.sortGoods("SECKILL");
|
||||
},
|
||||
};
|
||||
// case "COUPON":
|
||||
// return {
|
||||
// title: "优惠券",
|
||||
// methodsed: () => {
|
||||
// this.showPromotionList = [];
|
||||
// this.activeColumns = this.pintuanColumns;
|
||||
// this.sortGoods("COUPON");
|
||||
// },
|
||||
// };
|
||||
return { title: "秒杀", methodsed: () => { this.showPromotionList = []; this.sortGoods("SECKILL"); } };
|
||||
case "POINTS_GOODS":
|
||||
return {
|
||||
title: "积分商品",
|
||||
methodsed: () => {
|
||||
this.showPromotionList = [];
|
||||
this.activeColumns = this.pintuanColumns;
|
||||
this.sortGoods("POINTS_GOODS");
|
||||
},
|
||||
};
|
||||
return { title: "积分商品", methodsed: () => { this.showPromotionList = []; this.sortGoods("POINTS_GOODS"); } };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
// 选择活动
|
||||
selectedPromotion(val) {
|
||||
val.row.___type = "marketing";
|
||||
val.row.___promotion = this.promotions;
|
||||
this.$emit("selected", [val.row]);
|
||||
|
||||
this.index = val.index;
|
||||
},
|
||||
// 获取所有营销的活动
|
||||
async init() {
|
||||
let res = await getAllPromotion();
|
||||
const res = await getAllPromotion();
|
||||
if (res.success) {
|
||||
this.loading = false;
|
||||
this.getPromotion(res);
|
||||
// this.clickPromotion(this.typeOption[Object.keys(res.result)[0]], 0);
|
||||
} else {
|
||||
this.loading = false;
|
||||
}
|
||||
@@ -376,43 +148,25 @@ export default {
|
||||
getPromotion(res) {
|
||||
if (res.result) {
|
||||
this.promotionList = res.result;
|
||||
// 去除优惠券
|
||||
delete this.promotionList.COUPON;
|
||||
Object.keys(res.result)[0] && this.typeOption(Object.keys(res.result)[0]).methodsed();
|
||||
this.promotions = Object.keys(res.result)[0];
|
||||
}
|
||||
|
||||
// if (Object.keys(res.result).length) {
|
||||
// this.typeOption[Object.keys(res.result)[0]].methodsed(
|
||||
// this.promotionList[Object.keys(res.result)[0]].id
|
||||
// );
|
||||
// }
|
||||
},
|
||||
|
||||
// 点击某个活动查询活动列表
|
||||
clickPromotion(val, i) {
|
||||
this.promotions = val;
|
||||
this.selectedIndex = i;
|
||||
this.params.pageNumber = 1;
|
||||
this.typeOption(val) &&
|
||||
this.typeOption(val).methodsed(this.promotionList[val].id);
|
||||
this.typeOption(val) && this.typeOption(val).methodsed(this.promotionList[val].id);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
img {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
.search {
|
||||
width: 300px;
|
||||
}
|
||||
.page {
|
||||
margin-top: 2vh;
|
||||
text-align: right;
|
||||
}
|
||||
.time {
|
||||
font-size: 12px;
|
||||
.link-text {
|
||||
color: #2d8cf0;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
.tables {
|
||||
height: 400px;
|
||||
@@ -420,13 +174,12 @@ img {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
}
|
||||
::v-deep .ivu-table-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
.list {
|
||||
margin: 0 1.5%;
|
||||
height: 400px;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
width: auto;
|
||||
> .list-item {
|
||||
padding: 10px;
|
||||
transition: 0.35s;
|
||||
@@ -436,10 +189,6 @@ img {
|
||||
background: #ededed;
|
||||
}
|
||||
}
|
||||
.list {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
}
|
||||
.content {
|
||||
overflow: hidden;
|
||||
flex: 4;
|
||||
@@ -449,11 +198,6 @@ img {
|
||||
}
|
||||
.wrapper {
|
||||
overflow: hidden;
|
||||
}
|
||||
.search-views {
|
||||
display: flex;
|
||||
> * {
|
||||
margin: 0 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,142 +1,103 @@
|
||||
<template>
|
||||
<div>
|
||||
<Row :gutter="30">
|
||||
<Col
|
||||
span="4"
|
||||
v-for="(item, index) in linkList"
|
||||
:key="index"
|
||||
v-if="
|
||||
(item.title !== '拼团频道' && item.title !== '签到') ||
|
||||
$route.name !== 'renovation'
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="card"
|
||||
:class="{ active: selectedIndex == index }"
|
||||
@click="handleLink(item, index)"
|
||||
<el-row :gutter="30">
|
||||
<template v-for="(item, index) in linkList" :key="index">
|
||||
<el-col
|
||||
v-if="showLinkItem(item)"
|
||||
:span="4"
|
||||
>
|
||||
<Icon size="24" :type="item.icon" />
|
||||
<p>{{ item.title }}</p>
|
||||
</div>
|
||||
</Col>
|
||||
<!-- 外部链接,只有pc端跳转 -->
|
||||
<Col span="4">
|
||||
<div
|
||||
class="card"
|
||||
:class="{ active: selectedIndex == index }"
|
||||
@click="handleLink(item, index)"
|
||||
>
|
||||
<el-icon :size="24">
|
||||
<component :is="item.icon" />
|
||||
</el-icon>
|
||||
<p>{{ item.title }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
</template>
|
||||
<el-col v-if="linkVisible" :span="4">
|
||||
<div
|
||||
v-if="linkVisible"
|
||||
class="card"
|
||||
:class="{ active: selectedIndex == linkList.length }"
|
||||
@click="handleLink(linkItem, linkList.length)"
|
||||
>
|
||||
<Icon size="24" :type="linkItem.icon" />
|
||||
<el-icon :size="24">
|
||||
<component :is="linkItem.icon" />
|
||||
</el-icon>
|
||||
<p>{{ linkItem.title }}</p>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { markRaw } from "vue";
|
||||
import {
|
||||
House,
|
||||
ShoppingCart,
|
||||
Star,
|
||||
Document,
|
||||
User,
|
||||
Promotion,
|
||||
PriceTag,
|
||||
Sunny,
|
||||
VideoCamera,
|
||||
Share,
|
||||
ShoppingBag,
|
||||
Link,
|
||||
} from "@element-plus/icons-vue";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
linkList: [
|
||||
// 链接列表
|
||||
{
|
||||
title: "首页",
|
||||
icon: "md-home",
|
||||
___type: "home",
|
||||
},
|
||||
{
|
||||
title: "购物车",
|
||||
icon: "md-cart",
|
||||
___type: "cart",
|
||||
},
|
||||
{
|
||||
title: "收藏商品",
|
||||
icon: "md-heart",
|
||||
___type: "collection",
|
||||
},
|
||||
{
|
||||
title: "我的订单",
|
||||
icon: "md-document",
|
||||
___type: "order",
|
||||
},
|
||||
{
|
||||
title: "个人中心",
|
||||
icon: "md-person",
|
||||
___type: "user",
|
||||
},
|
||||
{
|
||||
title: "拼团频道",
|
||||
icon: "md-flame",
|
||||
___type: "group",
|
||||
},
|
||||
{
|
||||
title: "秒杀频道",
|
||||
icon: "md-flame",
|
||||
___type: "seckill",
|
||||
},
|
||||
{
|
||||
title: "领券中心",
|
||||
icon: "md-pricetag",
|
||||
___type: "coupon",
|
||||
},
|
||||
{
|
||||
title: "签到",
|
||||
icon: "md-happy",
|
||||
___type: "sign",
|
||||
},
|
||||
{
|
||||
title: "小程序直播",
|
||||
icon: "ios-videocam",
|
||||
___type: "live",
|
||||
},
|
||||
{
|
||||
title: "砍价",
|
||||
icon: "md-share-alt",
|
||||
___type: "kanjia",
|
||||
},
|
||||
{
|
||||
title: "积分商城",
|
||||
icon: "ios-basket",
|
||||
___type: "point",
|
||||
},
|
||||
{ title: "首页", icon: markRaw(House), ___type: "home" },
|
||||
{ title: "购物车", icon: markRaw(ShoppingCart), ___type: "cart" },
|
||||
{ title: "收藏商品", icon: markRaw(Star), ___type: "collection" },
|
||||
{ title: "我的订单", icon: markRaw(Document), ___type: "order" },
|
||||
{ title: "个人中心", icon: markRaw(User), ___type: "user" },
|
||||
{ title: "拼团频道", icon: markRaw(Promotion), ___type: "group" },
|
||||
{ title: "秒杀频道", icon: markRaw(Promotion), ___type: "seckill" },
|
||||
{ title: "领券中心", icon: markRaw(PriceTag), ___type: "coupon" },
|
||||
{ title: "签到", icon: markRaw(Sunny), ___type: "sign" },
|
||||
{ title: "小程序直播", icon: markRaw(VideoCamera), ___type: "live" },
|
||||
{ title: "砍价", icon: markRaw(Share), ___type: "kanjia" },
|
||||
{ title: "积分商城", icon: markRaw(ShoppingBag), ___type: "point" },
|
||||
],
|
||||
linkItem: {
|
||||
title: "外部链接",
|
||||
icon: "ios-link",
|
||||
icon: markRaw(Link),
|
||||
___type: "link",
|
||||
url: "",
|
||||
},
|
||||
linkVisible: true, // 是否显示外部链接
|
||||
selectedIndex: 9999999, // 已选index
|
||||
linkVisible: true,
|
||||
selectedIndex: 9999999,
|
||||
};
|
||||
},
|
||||
created(){
|
||||
// console.log(window.location.href)
|
||||
let urls = window.location.href
|
||||
if(urls.indexOf('/floorList/renovation') != -1){
|
||||
this.linkList.forEach((items,indexs)=>{
|
||||
if(items.title == '砍价'){
|
||||
this.linkList.splice(indexs,1)
|
||||
}
|
||||
})
|
||||
this.linkList.forEach((item,index)=>{
|
||||
if(item.title == '小程序直播'){
|
||||
this.linkList.splice(index,1)
|
||||
}
|
||||
})
|
||||
this.linkList.forEach((itemss,indexss)=>{
|
||||
if(itemss.title == '积分商城'){
|
||||
this.linkList.splice(indexss,1)
|
||||
}
|
||||
})
|
||||
this.linkVisible = true
|
||||
}else{
|
||||
this.linkVisible = false
|
||||
created() {
|
||||
const urls = window.location.href;
|
||||
if (urls.indexOf("/floorList/renovation") != -1) {
|
||||
this.linkList = this.linkList.filter(
|
||||
(item) =>
|
||||
item.title !== "砍价" &&
|
||||
item.title !== "小程序直播" &&
|
||||
item.title !== "积分商城"
|
||||
);
|
||||
this.linkVisible = true;
|
||||
} else {
|
||||
this.linkVisible = false;
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
showLinkItem(item) {
|
||||
return (
|
||||
(item.title !== "拼团频道" && item.title !== "签到") ||
|
||||
this.$route.name !== "renovation"
|
||||
);
|
||||
},
|
||||
handleLink(val, index) {
|
||||
val = { ...val, ___type: "other" };
|
||||
this.selectedIndex = index;
|
||||
@@ -157,7 +118,7 @@ export default {
|
||||
text-align: center;
|
||||
transition: 0.35s;
|
||||
cursor: pointer;
|
||||
::v-deep p {
|
||||
:deep(p) {
|
||||
margin: 10px 0;
|
||||
}
|
||||
border: 1px solid #ededed;
|
||||
|
||||
@@ -33,7 +33,7 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .ivu-card-body {
|
||||
:deep(.ivu-card-body){
|
||||
height: 414px;
|
||||
overflow: auto;
|
||||
}
|
||||
@@ -69,11 +69,11 @@ export default {
|
||||
height: 416px;
|
||||
overflow: hidden;
|
||||
}
|
||||
::v-deep .ivu-table {
|
||||
:deep(.ivu-table){
|
||||
height: 300px !important;
|
||||
overflow: auto;
|
||||
}
|
||||
::v-deep .ivu-card-body {
|
||||
:deep(.ivu-card-body){
|
||||
padding: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@@ -4,40 +4,54 @@
|
||||
<div class="query-wrapper">
|
||||
<div class="query-item">
|
||||
<div>店铺名称</div>
|
||||
<Input placeholder="请输入店铺名称" @on-clear="shopsData=[]; params.storeName=''; params.pageNumber =1; init()" @on-enter="()=>{shopsData=[]; params.pageNumber =1; init();}" icon="ios-search" clearable style="width: 150px"
|
||||
v-model="params.storeName" />
|
||||
<el-input
|
||||
v-model="params.storeName"
|
||||
placeholder="请输入店铺名称"
|
||||
clearable
|
||||
style="width: 150px"
|
||||
@clear="resetSearch"
|
||||
@keyup.enter="resetSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="query-item">
|
||||
<Button type="primary" @click="shopsData=[];params.pageNumber =1; init();" icon="ios-search">搜索</Button>
|
||||
<el-button type="primary" @click="resetSearch">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="wap-content-list" >
|
||||
<div class="wap-content-item" @click="clickShop(item,index)" :class="{ active:selected == index }" v-for="(item, index) in shopsData" :key="index">
|
||||
<div v-loading="loading" class="wap-content-list">
|
||||
<div
|
||||
v-for="(item, index) in shopsData"
|
||||
:key="index"
|
||||
class="wap-content-item"
|
||||
:class="{ active: selected == index }"
|
||||
@click="clickShop(item, index)"
|
||||
>
|
||||
<div>
|
||||
<img class="shop-logo" :src="item.storeLogo" alt="" />
|
||||
</div>
|
||||
<div class="wap-content-desc">
|
||||
<div class="wap-content-desc-title">{{ item.storeName }}</div>
|
||||
|
||||
<div class="self-operated" :class="{'theme_color':item.selfOperated }">{{ item.selfOperated ? '自营' : '非自营' }}</div>
|
||||
<div class="wap-sku" :class="{'theme_color':(item.storeDisable === 'OPEN' ? true : false) }">{{ item.storeDisable === 'OPEN' ? '开启中' : '未开启' }}</div>
|
||||
<div class="self-operated" :class="{ theme_color: item.selfOperated }">
|
||||
{{ item.selfOperated ? "自营" : "非自营" }}
|
||||
</div>
|
||||
<div
|
||||
class="wap-sku"
|
||||
:class="{ theme_color: item.storeDisable === 'OPEN' }"
|
||||
>
|
||||
{{ item.storeDisable === "OPEN" ? "开启中" : "未开启" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Spin size="large" fix v-if="loading"></Spin>
|
||||
</div>
|
||||
<Page
|
||||
:total="total"
|
||||
<el-pagination
|
||||
class="pageration"
|
||||
@on-change="changePageSize"
|
||||
:page-size="params.pageSize"
|
||||
size="small"
|
||||
show-total
|
||||
show-elevator
|
||||
|
||||
>
|
||||
</Page>
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
:page-size="params.pageSize"
|
||||
:current-page="params.pageNumber"
|
||||
@current-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,25 +61,28 @@ import { getShopListData } from "@/api/shops.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false, // 加载状态
|
||||
total: "", // 总数
|
||||
params: { // 请求参数
|
||||
loading: false,
|
||||
total: 0,
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 12,
|
||||
storeDisable: "OPEN",
|
||||
storeName: "",
|
||||
},
|
||||
shopsData: [], // 店铺数据
|
||||
selected: 9999999999, //设置一个不可能选中的index
|
||||
shopsData: [],
|
||||
selected: 9999999999,
|
||||
};
|
||||
},
|
||||
watch: {},
|
||||
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
changePageSize(v){
|
||||
resetSearch() {
|
||||
this.shopsData = [];
|
||||
this.params.pageNumber = 1;
|
||||
this.init();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.params.pageNumber = v;
|
||||
this.init();
|
||||
},
|
||||
@@ -73,15 +90,10 @@ export default {
|
||||
this.loading = true;
|
||||
getShopListData(this.params).then((res) => {
|
||||
if (res.success) {
|
||||
/**
|
||||
* 解决数据请求中,滚动栏会一直上下跳动
|
||||
*/
|
||||
this.total = res.result.total;
|
||||
|
||||
this.shopsData = res.result.records;
|
||||
|
||||
this.loading = false;
|
||||
}
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
clickShop(val, i) {
|
||||
@@ -105,15 +117,18 @@ export default {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
height: 340px;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.shop-logo {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: url("../../../assets/selected.png") no-repeat;
|
||||
background-position: right;
|
||||
background-size: 10%;
|
||||
}
|
||||
.pageration {
|
||||
margin-top: 12px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,26 +3,31 @@
|
||||
<div class="content">
|
||||
<div>
|
||||
<div class="tables">
|
||||
<Table
|
||||
border
|
||||
height="350"
|
||||
tooltip
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
>
|
||||
</Table>
|
||||
<el-table v-loading="loading" border height="350" :data="data" style="width: 100%">
|
||||
<el-table-column prop="name" label="专题名称" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" fixed="right" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-button
|
||||
v-if="row"
|
||||
:type="index === $index ? 'primary' : 'default'"
|
||||
size="small"
|
||||
@click="selectRow(row, $index)"
|
||||
>
|
||||
{{ index === $index ? "已选" : "选择" }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<Page
|
||||
|
||||
@on-change="changePageNum"
|
||||
@on-page-size-change="changePageSize"
|
||||
:current="params.pageNumber"
|
||||
:page-size="params.pageSize"
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
class="mt_10"
|
||||
:total="Number(total)"
|
||||
layout="prev, pager, next, jumper"
|
||||
size="small"
|
||||
show-elevator
|
||||
@current-change="changePageNum"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30,16 +35,13 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getHomeList } from "@/api/other.js";
|
||||
import { getHomeList } from "@/api/other.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: true, //表格请求数据为true
|
||||
promotionList: "", // 活动列表
|
||||
selectedIndex: 0, //左侧菜单选择
|
||||
promotions: "", //选中的活动key
|
||||
index: 999, // 已选下标
|
||||
data:[],
|
||||
loading: true,
|
||||
index: 999,
|
||||
data: [],
|
||||
params: {
|
||||
sort: "createTime",
|
||||
order: "desc",
|
||||
@@ -48,68 +50,34 @@ export default {
|
||||
pageSize: 20,
|
||||
pageType: "SPECIAL",
|
||||
},
|
||||
total: 0, // 表单数据总数
|
||||
columns: [
|
||||
{
|
||||
title: "专题名称",
|
||||
key: "name",
|
||||
tooltip: true,
|
||||
// slot: 'name'
|
||||
// width: 200,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
fixed: "right",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: this.index == params.index ? "primary" : "default",
|
||||
size: "small",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.index = params.index;
|
||||
params.row = {...params.row,pageType:'special',___type:'special'}
|
||||
this.$emit("selected", [params.row]);
|
||||
},
|
||||
},
|
||||
},
|
||||
this.index == params.index ? "已选" : "选择"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
total: 0,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
methods: {
|
||||
changePageNum (val) { // 修改评论页码
|
||||
selectRow(row, idx) {
|
||||
this.index = idx;
|
||||
const payload = { ...row, pageType: "special", ___type: "special" };
|
||||
this.$emit("selected", [payload]);
|
||||
},
|
||||
changePageNum(val) {
|
||||
this.params.pageNumber = val;
|
||||
this.init();
|
||||
},
|
||||
changePageSize (val) { // 修改评论页数
|
||||
changePageSize(val) {
|
||||
this.params.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.init();
|
||||
},
|
||||
// 获取话题的标题
|
||||
async init() {
|
||||
// 根据当前路径判断当前是H5还是PC
|
||||
this.params.pageClientType = this.$route.name === 'renovation' ? 'PC' : 'H5'
|
||||
let res = await getHomeList(this.params);
|
||||
this.params.pageClientType = this.$route.name === "renovation" ? "PC" : "H5";
|
||||
const res = await getHomeList(this.params);
|
||||
if (res.success) {
|
||||
this.loading = false;
|
||||
this.data= res.result.records
|
||||
this.total = res.result.total
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
} else {
|
||||
this.loading = false;
|
||||
}
|
||||
@@ -128,49 +96,17 @@ img {
|
||||
margin-top: 2vh;
|
||||
text-align: right;
|
||||
}
|
||||
.time {
|
||||
font-size: 12px;
|
||||
}
|
||||
.tables {
|
||||
height: 400px;
|
||||
margin-top: 20px;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
}
|
||||
::v-deep .ivu-table-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
.list {
|
||||
margin: 0 1.5%;
|
||||
height: 400px;
|
||||
overflow: auto;
|
||||
> .list-item {
|
||||
padding: 10px;
|
||||
transition: 0.35s;
|
||||
cursor: pointer;
|
||||
}
|
||||
.list-item:hover {
|
||||
background: #ededed;
|
||||
}
|
||||
}
|
||||
.list {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
}
|
||||
.content {
|
||||
overflow: hidden;
|
||||
flex: 4;
|
||||
}
|
||||
.active {
|
||||
background: #ededed;
|
||||
}
|
||||
.wrapper {
|
||||
overflow: hidden;
|
||||
}
|
||||
.search-views {
|
||||
display: flex;
|
||||
> * {
|
||||
margin: 0 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
<template>
|
||||
<div style="display: inline-block;">
|
||||
<Icon type="ios-loading" size="18" color="#2d8cf0" class="spin-icon-load"></Icon>
|
||||
<div style="display: inline-block">
|
||||
<el-icon class="spin-icon-load" :size="18" color="#ff5c58">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Loading } from "@element-plus/icons-vue";
|
||||
|
||||
export default {
|
||||
name: "circleLoading"
|
||||
name: "circleLoading",
|
||||
components: { Loading },
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -14,5 +19,12 @@ export default {
|
||||
.spin-icon-load {
|
||||
animation: ani-demo-spin 1s linear infinite;
|
||||
}
|
||||
@keyframes ani-demo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,78 +1,34 @@
|
||||
<template>
|
||||
<div>
|
||||
<Drawer width="300px" title="页面配置" v-model="drawer">
|
||||
<!-- 内容 -->
|
||||
<h3>
|
||||
内容设置
|
||||
</h3>
|
||||
<div class="config-item flex flex-a-c flex-j-sb">
|
||||
<div>
|
||||
<Tooltip theme="light" placement="bottom-end" max-width="100" content="关闭之后部分页面点击'查看''详情'等按钮将跳到新页面展示" >
|
||||
<div>
|
||||
多标签Tab页内嵌模式
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<i-switch v-model="setting.isUseTabsRouter"></i-switch>
|
||||
</div>
|
||||
</Drawer>
|
||||
<el-drawer v-model="drawer" title="页面配置" size="300px">
|
||||
<div class="config-empty">暂无可配置项</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
export default {
|
||||
name: "configDrawer",
|
||||
data() {
|
||||
return {
|
||||
drawer: false,
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
setting: state => {
|
||||
return state.setting.setting
|
||||
}
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
setting: {
|
||||
handler(val) {
|
||||
this.setStore('admin-setting', val)
|
||||
this.$store.commit('updateSetting', val);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.drawer = true
|
||||
this.drawer = true;
|
||||
},
|
||||
close() {
|
||||
this.drawer = false
|
||||
this.drawer = false;
|
||||
},
|
||||
toggle() {
|
||||
this.drawer != this.drawer
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
* {
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 10px 0 20px 0;
|
||||
}
|
||||
|
||||
.config-item {
|
||||
cursor: pointer;
|
||||
margin-bottom: 20px;
|
||||
justify-content: space-between;
|
||||
<style scoped>
|
||||
.config-empty {
|
||||
color: #909399;
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,72 +1,68 @@
|
||||
<template>
|
||||
<div>
|
||||
<Cascader
|
||||
<el-cascader
|
||||
v-model="selectDep"
|
||||
:data="department"
|
||||
@on-change="handleChangeDep"
|
||||
change-on-select
|
||||
:options="department"
|
||||
:props="cascaderProps"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
></Cascader>
|
||||
style="width: 100%"
|
||||
@change="handleChangeDep"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { initDepartment } from "@/api/index";
|
||||
|
||||
export default {
|
||||
name: "departmentChoose",
|
||||
props: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectDep: [], // 已选数据
|
||||
department: [] // 列表
|
||||
selectDep: [],
|
||||
department: [],
|
||||
cascaderProps: {
|
||||
value: "value",
|
||||
label: "label",
|
||||
children: "children",
|
||||
checkStrictly: true,
|
||||
emitPath: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 获取部门数据
|
||||
initDepartmentData() {
|
||||
initDepartment().then(res => {
|
||||
initDepartment().then((res) => {
|
||||
if (res.success) {
|
||||
const arr = res.result;
|
||||
this.filterData(arr)
|
||||
this.department = arr
|
||||
this.filterData(arr);
|
||||
this.department = arr;
|
||||
}
|
||||
});
|
||||
},
|
||||
handleChangeDep(value, selectedData) {
|
||||
handleChangeDep(value) {
|
||||
let departmentId = "";
|
||||
// 获取最后一个值
|
||||
if (value && value.length > 0) {
|
||||
departmentId = value[value.length - 1];
|
||||
}
|
||||
this.$emit("on-change", departmentId);
|
||||
},
|
||||
// 清空已选列表
|
||||
clearSelect() {
|
||||
this.selectDep = [];
|
||||
},
|
||||
// 处理部门数据
|
||||
filterData (data) {
|
||||
data.forEach(e => {
|
||||
filterData(data) {
|
||||
data.forEach((e) => {
|
||||
e.value = e.id;
|
||||
e.label = e.title;
|
||||
if (e.children) {
|
||||
this.filterData(e.children)
|
||||
} else {
|
||||
return
|
||||
this.filterData(e.children);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initDepartmentData();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,106 +1,110 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="display:flex;">
|
||||
<Input
|
||||
<div style="display: flex">
|
||||
<el-input
|
||||
v-model="departmentTitle"
|
||||
readonly
|
||||
style="margin-right:10px;"
|
||||
style="margin-right: 10px; flex: 1"
|
||||
:placeholder="placeholder"
|
||||
:clearable="clearable"
|
||||
@on-clear="clearSelect"
|
||||
@clear="clearSelect"
|
||||
/>
|
||||
<Poptip transfer trigger="click" placement="right" title="选择部门" width="250">
|
||||
<Button icon="md-list">选择部门</Button>
|
||||
<div slot="content">
|
||||
<Input
|
||||
v-model="searchKey"
|
||||
suffix="ios-search"
|
||||
@on-change="searchDep"
|
||||
placeholder="输入部门名搜索"
|
||||
clearable
|
||||
<el-popover trigger="click" placement="right" title="选择部门" :width="280">
|
||||
<template #reference>
|
||||
<el-button>选择部门</el-button>
|
||||
</template>
|
||||
<el-input
|
||||
v-model="searchKey"
|
||||
placeholder="输入部门名搜索"
|
||||
clearable
|
||||
style="margin-bottom: 8px"
|
||||
@input="searchDep"
|
||||
/>
|
||||
<div v-loading="depLoading" class="dep-tree-bar">
|
||||
<el-tree
|
||||
:data="dataDep"
|
||||
:props="treeProps"
|
||||
node-key="id"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
@node-click="selectTree"
|
||||
/>
|
||||
<div class="dep-tree-bar">
|
||||
<Tree
|
||||
:data="dataDep"
|
||||
@on-select-change="selectTree"
|
||||
></Tree>
|
||||
<Spin size="large" fix v-if="depLoading"></Spin>
|
||||
</div>
|
||||
</div>
|
||||
</Poptip>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {initDepartment, searchDepartment} from "@/api/index";
|
||||
import { initDepartment } from "@/api/index";
|
||||
|
||||
export default {
|
||||
name: "departmentTreeChoose",
|
||||
props: {
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "点击选择部门"
|
||||
}
|
||||
default: "点击选择部门",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
depLoading: false, // 加载状态
|
||||
departmentTitle: "", // modal标题
|
||||
searchKey: "", // 搜索关键词
|
||||
dataDep: [], // 部门列表
|
||||
cloneDep: [], // 克隆部门列表
|
||||
selectDep: [], // 已选部门
|
||||
departmentId: [] // 部门id
|
||||
depLoading: false,
|
||||
departmentTitle: "",
|
||||
searchKey: "",
|
||||
dataDep: [],
|
||||
cloneDep: [],
|
||||
departmentId: [],
|
||||
treeProps: {
|
||||
label: "title",
|
||||
children: "children",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 获取部门数据
|
||||
initDepartmentData() {
|
||||
initDepartment().then(res => {
|
||||
if (res.success) {
|
||||
this.dataDep = res.result;
|
||||
|
||||
this.cloneDep = JSON.parse(JSON.stringify(this.dataDep));
|
||||
}
|
||||
});
|
||||
this.depLoading = true;
|
||||
initDepartment()
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
this.dataDep = res.result;
|
||||
this.cloneDep = JSON.parse(JSON.stringify(this.dataDep));
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.depLoading = false;
|
||||
});
|
||||
},
|
||||
searchDep() {
|
||||
// 搜索部门
|
||||
if (this.searchKey) {
|
||||
this.dataDep = this.cloneDep.filter(item => {
|
||||
return item.title.indexOf(this.searchKey) > -1;
|
||||
});
|
||||
|
||||
this.dataDep = this.cloneDep.filter(
|
||||
(item) => item.title.indexOf(this.searchKey) > -1
|
||||
);
|
||||
} else {
|
||||
this.dataDep = JSON.parse(JSON.stringify(this.cloneDep));
|
||||
}
|
||||
},
|
||||
// 选择回调
|
||||
selectTree(v) {
|
||||
if (v.length === 0) {
|
||||
selectTree(node) {
|
||||
if (!node) {
|
||||
this.$emit("on-change", null);
|
||||
this.departmentId = "";
|
||||
this.departmentTitle = "";
|
||||
return
|
||||
return;
|
||||
}
|
||||
this.departmentId = v[0].id;
|
||||
this.departmentTitle = v[0].title;
|
||||
let department = {
|
||||
this.departmentId = node.id;
|
||||
this.departmentTitle = node.title;
|
||||
this.$emit("on-change", {
|
||||
departmentId: this.departmentId,
|
||||
departmentTitle: this.departmentTitle
|
||||
}
|
||||
this.$emit("on-change", department);
|
||||
departmentTitle: this.departmentTitle,
|
||||
});
|
||||
},
|
||||
// 清除选中方法
|
||||
clearSelect() {
|
||||
this.departmentId = [];
|
||||
this.departmentTitle = "";
|
||||
@@ -112,7 +116,6 @@ export default {
|
||||
}
|
||||
this.$emit("on-clear");
|
||||
},
|
||||
// 设置数据 回显用
|
||||
setData(ids, title) {
|
||||
this.departmentTitle = title;
|
||||
if (this.multiple) {
|
||||
@@ -121,11 +124,11 @@ export default {
|
||||
this.departmentId = [];
|
||||
this.departmentId.push(ids);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initDepartmentData();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -145,9 +148,6 @@ export default {
|
||||
|
||||
.dep-tree-bar::-webkit-scrollbar-thumb {
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: inset 0 0 2px #d1d1d1;
|
||||
background: #e4e4e4;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,30 +1,31 @@
|
||||
<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;"
|
||||
<el-popover trigger="focus" placement="right" :width="250">
|
||||
<template #reference>
|
||||
<el-input
|
||||
v-model="currentValue"
|
||||
type="password"
|
||||
show-password
|
||||
style="width: 350px"
|
||||
:maxlength="maxlength"
|
||||
:size="size"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
@input="handleChange"
|
||||
/>
|
||||
<br />请至少输入 6 个字符。请不要使
|
||||
<br />用容易被猜到的密码。
|
||||
</template>
|
||||
<div :class="tipStyle">
|
||||
<div class="words">强度 : {{ strength }}</div>
|
||||
<el-progress
|
||||
:percentage="strengthValue"
|
||||
:status="progressStatus"
|
||||
:show-text="false"
|
||||
style="margin: 13px 0"
|
||||
/>
|
||||
<br />请至少输入 6 个字符。请不要使用容易被猜到的密码。
|
||||
</div>
|
||||
</Poptip>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -32,54 +33,53 @@
|
||||
export default {
|
||||
name: "setPassword",
|
||||
props: {
|
||||
modelValue: String,
|
||||
value: String,
|
||||
size: String,
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "请输入密码,长度为6-20个字符"
|
||||
default: "请输入密码,长度为6-20个字符",
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: 20
|
||||
}
|
||||
default: 20,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue", "input", "on-change"],
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value, // 当前值
|
||||
tipStyle: "password-tip-none", // 强度样式
|
||||
strengthValue: 0, // 强度等级
|
||||
progressStatus: "normal", // 进度条状态
|
||||
strength: "无", // 密码强度描述
|
||||
grade: 0 // 强度等级
|
||||
currentValue: this.modelValue ?? this.value ?? "",
|
||||
tipStyle: "password-tip-none",
|
||||
strengthValue: 0,
|
||||
progressStatus: "",
|
||||
strength: "无",
|
||||
grade: 0,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
modelValue(val) {
|
||||
this.setCurrentValue(val);
|
||||
},
|
||||
value(val) {
|
||||
this.setCurrentValue(val);
|
||||
},
|
||||
},
|
||||
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++;
|
||||
}
|
||||
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;
|
||||
},
|
||||
@@ -90,14 +90,14 @@ export default {
|
||||
this.strengthValue = 0;
|
||||
return;
|
||||
}
|
||||
let grade = this.checkStrengthValue(this.currentValue);
|
||||
const grade = this.checkStrengthValue(this.currentValue);
|
||||
if (grade <= 1) {
|
||||
this.progressStatus = "wrong";
|
||||
this.progressStatus = "exception";
|
||||
this.tipStyle = "password-tip-weak";
|
||||
this.strength = "弱";
|
||||
this.strengthValue = 33;
|
||||
} else if (grade >= 2 && grade <= 4) {
|
||||
this.progressStatus = "normal";
|
||||
this.progressStatus = "";
|
||||
this.tipStyle = "password-tip-middle";
|
||||
this.strength = "中";
|
||||
this.strengthValue = 66;
|
||||
@@ -108,61 +108,33 @@ export default {
|
||||
this.strengthValue = 100;
|
||||
}
|
||||
},
|
||||
// 密码变动后回调
|
||||
handleChange(v) {
|
||||
handleChange() {
|
||||
this.strengthChange();
|
||||
this.$emit("update:modelValue", this.currentValue);
|
||||
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;
|
||||
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-weak .words {
|
||||
color: #ed3f14;
|
||||
}
|
||||
|
||||
.password-tip-middle {
|
||||
padding: 1vh 0;
|
||||
|
||||
.words {
|
||||
color: #2d8cf0;
|
||||
}
|
||||
.password-tip-middle .words {
|
||||
color: #2d8cf0;
|
||||
}
|
||||
|
||||
.password-tip-strong {
|
||||
padding: 1vh 0;
|
||||
|
||||
.words {
|
||||
color: #52c41a;
|
||||
}
|
||||
.password-tip-strong .words {
|
||||
color: #52c41a;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,210 +1,166 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="display:flex;">
|
||||
<Input
|
||||
<div style="display: flex; gap: 10px; align-items: center; width: 100%">
|
||||
<el-input
|
||||
v-if="showInput"
|
||||
v-model="currentValue"
|
||||
@on-change="handleChange"
|
||||
v-show="showInput"
|
||||
:placeholder="placeholder"
|
||||
:size="size"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:maxlength="maxlength"
|
||||
style="flex: 1"
|
||||
@input="handleChange"
|
||||
>
|
||||
<Poptip slot="append" transfer trigger="hover" title="图片预览" placement="right">
|
||||
<Icon type="md-eye" class="see-icon" />
|
||||
<div slot="content">
|
||||
<img :src="currentValue" alt="该资源不存在" style="max-width: 300px;margin: 0 auto;display: block;" />
|
||||
<a @click="viewImage=true" style="margin-top:5px;text-align:right;display:block">查看大图</a>
|
||||
</div>
|
||||
</Poptip>
|
||||
</Input>
|
||||
<Button @click="handleCLickImg('storeLogo')">选择图片</Button>
|
||||
<!--<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="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">上传图片</Button>-->
|
||||
<!--</Upload>-->
|
||||
<template #append>
|
||||
<el-popover trigger="hover" placement="right" :width="320" title="图片预览">
|
||||
<template #reference>
|
||||
<el-button class="see-icon">
|
||||
<el-icon><View /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
<img
|
||||
v-if="currentValue"
|
||||
:src="currentValue"
|
||||
alt="该资源不存在"
|
||||
style="max-width: 280px; display: block; margin: 0 auto"
|
||||
/>
|
||||
<el-button
|
||||
v-if="currentValue"
|
||||
type="primary"
|
||||
link
|
||||
style="margin-top: 8px; display: block; text-align: right"
|
||||
@click="viewImage = true"
|
||||
>
|
||||
查看大图
|
||||
</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-button @click="handleCLickImg('storeLogo')">选择图片</el-button>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
title="图片预览"
|
||||
v-model="viewImage"
|
||||
:styles="{ top: '30px' }"
|
||||
:z-index="3500"
|
||||
draggable
|
||||
>
|
||||
<img :src="currentValue" alt="该资源不存在" style="max-width: 300px;margin: 0 auto;display: block;" />
|
||||
<div slot="footer">
|
||||
<Button @click="viewImage=false">关闭</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal width="1200px" v-model="picModalFlag" :z-index="3500">
|
||||
<ossManage @callback="callbackSelected" ref="ossManage" :isComponent="true" :initialize="picModalFlag" />
|
||||
</Modal>
|
||||
<el-dialog v-model="viewImage" title="图片预览" width="480px" append-to-body :z-index="3500">
|
||||
<img
|
||||
:src="currentValue"
|
||||
alt="该资源不存在"
|
||||
style="max-width: 100%; margin: 0 auto; display: block"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="viewImage = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="picModalFlag" width="1200px" append-to-body :z-index="3500" destroy-on-close>
|
||||
<ossManage
|
||||
ref="ossManage"
|
||||
:is-component="true"
|
||||
:initialize="picModalFlag"
|
||||
@callback="callbackSelected"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { View } from "@element-plus/icons-vue";
|
||||
import { uploadFile } from "@/api/index";
|
||||
import ossManage from "@/views/sys/oss-manage/ossManage";
|
||||
|
||||
export default {
|
||||
name: "uploadPicInput",
|
||||
components: {
|
||||
ossManage,
|
||||
View,
|
||||
},
|
||||
props: {
|
||||
modelValue: String,
|
||||
value: String,
|
||||
size: {
|
||||
default: 'default',
|
||||
type: String
|
||||
default: "default",
|
||||
type: String,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "图片链接"
|
||||
default: "图片链接",
|
||||
},
|
||||
showInput: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
maxlength: Number,
|
||||
icon: {
|
||||
type: String,
|
||||
default: "ios-cloud-upload-outline"
|
||||
}
|
||||
},
|
||||
emits: ["update:modelValue", "input", "on-change"],
|
||||
data() {
|
||||
return {
|
||||
accessToken: {}, // 验证token
|
||||
currentValue: this.value, // 当前值
|
||||
loading: false, // 加载状态
|
||||
viewImage: false, // 预览图片modal
|
||||
uploadFileUrl: uploadFile, // 上传地址
|
||||
picModalFlag: false, // 图片选择器
|
||||
selectedFormBtnName: "", // 点击图片绑定form
|
||||
picIndex: "", // 存储身份证图片下标,方便赋值
|
||||
accessToken: {},
|
||||
currentValue: this.modelValue ?? this.value ?? "",
|
||||
viewImage: false,
|
||||
uploadFileUrl: uploadFile,
|
||||
picModalFlag: false,
|
||||
selectedFormBtnName: "",
|
||||
picIndex: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 选择图片modal
|
||||
handleCLickImg(val, index) {
|
||||
this.$refs.ossManage.selectImage = true;
|
||||
this.picModalFlag = true;
|
||||
this.selectedFormBtnName = val;
|
||||
this.picIndex = index;
|
||||
},
|
||||
// 图片回显
|
||||
callbackSelected(val) {
|
||||
this.picModalFlag = false;
|
||||
this.currentValue = val.url;
|
||||
this.picIndex = "";
|
||||
this.$emit("input", this.currentValue);
|
||||
this.$emit("on-change", this.currentValue);
|
||||
this.emitValue(this.currentValue);
|
||||
},
|
||||
// 初始化
|
||||
init() {
|
||||
this.accessToken = {
|
||||
accessToken: this.getStore("accessToken")
|
||||
accessToken: this.getStore("accessToken"),
|
||||
};
|
||||
},
|
||||
// 格式校验
|
||||
handleFormatError(file) {
|
||||
this.loading = false;
|
||||
this.$Notice.warning({
|
||||
title: "不支持的文件格式",
|
||||
desc:
|
||||
"所选文件‘ " +
|
||||
file.name +
|
||||
" ’格式不正确, 请选择 .jpg .jpeg .png .gif .bmp格式文件"
|
||||
});
|
||||
emitValue(val) {
|
||||
this.$emit("update:modelValue", val);
|
||||
this.$emit("input", val);
|
||||
this.$emit("on-change", val);
|
||||
},
|
||||
// 大小校验
|
||||
handleMaxSize(file) {
|
||||
this.loading = false;
|
||||
this.$Notice.warning({
|
||||
title: "文件大小过大",
|
||||
desc: "所选文件大小过大, 不得超过1M."
|
||||
});
|
||||
handleChange() {
|
||||
this.emitValue(this.currentValue);
|
||||
this.$attrs.rollback && this.$attrs.rollback();
|
||||
},
|
||||
// 上传前
|
||||
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("input", this.currentValue);
|
||||
this.$emit("on-change", this.currentValue);
|
||||
}
|
||||
this.currentValue = value ?? "";
|
||||
this.emitValue(this.currentValue);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue(val) {
|
||||
this.setCurrentValue(val);
|
||||
},
|
||||
value(val) {
|
||||
this.setCurrentValue(val);
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.see-icon {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.upload {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -3,187 +3,169 @@
|
||||
<div class="upload-pic-thumb">
|
||||
<vuedraggable
|
||||
:list="uploadList"
|
||||
:disabled="!draggable||!multiple"
|
||||
: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'" style="height:60px;">
|
||||
<img :src="item.url" />
|
||||
<div v-for="(item, index) in uploadList" :key="index" class="upload-list">
|
||||
<div v-if="item.status == 'finished'" style="height: 60px">
|
||||
<img :src="item.url" alt="" />
|
||||
<div class="upload-list-cover">
|
||||
<Icon type="ios-eye-outline" @click="handleView(item.url)"></Icon>
|
||||
<Icon type="ios-trash-outline" @click="handleRemove(item)"></Icon>
|
||||
<el-icon class="action-icon" @click="handleView(item.url)"><View /></el-icon>
|
||||
<el-icon class="action-icon" @click="handleRemove(item)"><Delete /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>
|
||||
<el-progress
|
||||
v-if="item.showProgress"
|
||||
:percentage="item.percentage"
|
||||
:show-text="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</vuedraggable>
|
||||
<Upload
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:multiple="multiple"
|
||||
:show-upload-list="false"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:format="['jpg','jpeg','png','gif']"
|
||||
:max-size="1024"
|
||||
:on-format-error="handleFormatError"
|
||||
:on-exceeded-size="handleMaxSize"
|
||||
:before-upload="handleBeforeUpload"
|
||||
type="drag"
|
||||
:action="uploadFileUrl"
|
||||
:headers="accessToken"
|
||||
style="display: inline-block;width:58px;"
|
||||
:multiple="multiple"
|
||||
:show-file-list="false"
|
||||
accept=".jpg,.jpeg,.png,.gif"
|
||||
drag
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
style="display: inline-block; width: 58px"
|
||||
>
|
||||
<div style="width: 58px;height:58px;line-height: 58px;">
|
||||
<Icon type="md-camera" size="20"></Icon>
|
||||
<div class="upload-trigger">
|
||||
<el-icon :size="20"><Camera /></el-icon>
|
||||
</div>
|
||||
</Upload>
|
||||
</el-upload>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<el-dialog v-model="viewImage" title="图片预览" width="520px" append-to-body>
|
||||
<img :src="imgUrl" alt="无效的图片链接" style="width: 100%; display: block; margin: 0 auto" />
|
||||
<template #footer>
|
||||
<el-button @click="viewImage = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Camera, Delete, View } from "@element-plus/icons-vue";
|
||||
import { uploadFile } from "@/api/index";
|
||||
import vuedraggable from "vuedraggable";
|
||||
|
||||
export default {
|
||||
name: "uploadPicThumb",
|
||||
components: {
|
||||
vuedraggable
|
||||
vuedraggable,
|
||||
Camera,
|
||||
Delete,
|
||||
View,
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: null
|
||||
},
|
||||
modelValue: { type: null },
|
||||
value: { type: null },
|
||||
draggable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 10
|
||||
}
|
||||
default: 10,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue", "input", "on-change", "uploadchange"],
|
||||
data() {
|
||||
return {
|
||||
accessToken: {}, // 验证token
|
||||
uploadFileUrl: uploadFile, // 上传地址
|
||||
uploadList: [], // 上传列表
|
||||
viewImage: false, // 预览modal
|
||||
imgUrl: "" // 图片地址
|
||||
accessToken: {},
|
||||
uploadFileUrl: uploadFile,
|
||||
uploadList: [],
|
||||
viewImage: false,
|
||||
imgUrl: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
bindValue() {
|
||||
return this.modelValue !== undefined ? this.modelValue : this.value;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 拖拽结束事件
|
||||
onEnd() {
|
||||
this.returnValue();
|
||||
},
|
||||
// 初始化方法
|
||||
init() {
|
||||
this.setData(this.value, true);
|
||||
this.setData(this.bindValue, true);
|
||||
this.accessToken = {
|
||||
accessToken: this.getStore("accessToken")
|
||||
accessToken: this.getStore("accessToken"),
|
||||
};
|
||||
},
|
||||
// 预览图片
|
||||
handleView(imgUrl) {
|
||||
this.imgUrl = imgUrl;
|
||||
this.viewImage = true;
|
||||
},
|
||||
// 移除图片
|
||||
handleRemove(file) {
|
||||
this.uploadList = this.uploadList.filter(i => i.url !== file.url);
|
||||
this.uploadList = this.uploadList.filter((i) => i.url !== file.url);
|
||||
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) {
|
||||
handleError(error) {
|
||||
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:
|
||||
"所选文件大小过大,不能超过1M."
|
||||
});
|
||||
},
|
||||
// 上传之前钩子
|
||||
handleBeforeUpload() {
|
||||
handleBeforeUpload(file) {
|
||||
const okType = ["image/jpeg", "image/png", "image/gif", "image/jpg"].includes(file.type);
|
||||
if (!okType) {
|
||||
this.$Message.warning("请选择 .jpg .jpeg .png .gif 格式图片");
|
||||
return false;
|
||||
}
|
||||
if (file.size / 1024 > 1024) {
|
||||
this.$Message.warning("所选文件大小过大,不能超过 1M");
|
||||
return false;
|
||||
}
|
||||
if (this.multiple && this.uploadList.length >= this.limit) {
|
||||
this.$Message.warning("最多只能上传" + this.limit + "张图片");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 返回组件值
|
||||
emitValue(val) {
|
||||
this.$emit("update:modelValue", val);
|
||||
this.$emit("input", val);
|
||||
this.$emit("on-change", val);
|
||||
},
|
||||
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", []);
|
||||
}
|
||||
const empty = this.multiple ? [] : "";
|
||||
this.emitValue(empty);
|
||||
return;
|
||||
}
|
||||
if (!this.multiple) {
|
||||
// 单张
|
||||
let v = this.uploadList[0].url;
|
||||
this.$emit("input", v);
|
||||
this.$emit("on-change", v);
|
||||
this.emitValue(this.uploadList[0].url);
|
||||
} else {
|
||||
let v = [];
|
||||
this.uploadList.forEach(e => {
|
||||
v.push(e.url);
|
||||
});
|
||||
this.$emit("input", v);
|
||||
this.$emit("on-change", v);
|
||||
this.emitValue(this.uploadList.map((e) => e.url));
|
||||
}
|
||||
},
|
||||
// 传入值变化时改变值
|
||||
setData(v, init) {
|
||||
if (typeof v == "string") {
|
||||
// 单张
|
||||
if (this.multiple) {
|
||||
this.$Message.warning("多张上传仅支持数组数据类型");
|
||||
return;
|
||||
@@ -191,60 +173,49 @@ export default {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
this.uploadList = [];
|
||||
let item = {
|
||||
url: v,
|
||||
status: "finished"
|
||||
};
|
||||
this.uploadList.push(item);
|
||||
this.uploadList = [{ url: v, status: "finished" }];
|
||||
this.$emit("uploadchange", v);
|
||||
this.$emit("on-change", v);
|
||||
} else if (typeof v == "object") {
|
||||
// 多张
|
||||
this.emitValue(v);
|
||||
} else if (typeof v == "object" && v) {
|
||||
if (!this.multiple) {
|
||||
this.$Message.warning("单张上传仅支持字符串数据类型");
|
||||
return;
|
||||
}
|
||||
this.uploadList = [];
|
||||
const list = v.length > this.limit ? v.slice(0, this.limit) : v;
|
||||
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 = {
|
||||
status: "finished",
|
||||
...e
|
||||
};
|
||||
this.uploadList.push(item);
|
||||
}
|
||||
list.forEach((e) => {
|
||||
this.uploadList.push({
|
||||
status: "finished",
|
||||
...(typeof e === "string" ? { url: e } : e),
|
||||
});
|
||||
this.$emit("on-change", v);
|
||||
});
|
||||
if (init) {
|
||||
this.emitValue(list);
|
||||
} else {
|
||||
this.$emit("on-change", list);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue(val) {
|
||||
this.setData(val);
|
||||
},
|
||||
value(val) {
|
||||
this.setData(val);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upload-pic-thumb{
|
||||
.upload-pic-thumb {
|
||||
display: flex;
|
||||
}
|
||||
.upload-list {
|
||||
@@ -264,7 +235,8 @@ export default {
|
||||
}
|
||||
.upload-list img {
|
||||
width: 100%;
|
||||
height: -webkit-fill-available;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.upload-list-cover {
|
||||
display: none;
|
||||
@@ -274,15 +246,17 @@ export default {
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.upload-list:hover .upload-list-cover {
|
||||
display: block;
|
||||
display: flex;
|
||||
}
|
||||
.upload-list-cover i {
|
||||
.action-icon {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
margin: 0 2px;
|
||||
}
|
||||
.list-group {
|
||||
display: inline-block;
|
||||
@@ -291,4 +265,12 @@ export default {
|
||||
opacity: 0.5;
|
||||
background: #c8ebfb;
|
||||
}
|
||||
.upload-trigger {
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
line-height: 58px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div id="map-container"></div>
|
||||
|
||||
<div class="search-con">
|
||||
<Input placeholder="输入关键字搜索" id="input-map" v-model="mapSearch" />
|
||||
<el-input id="input-map" v-model="mapSearch" placeholder="输入关键字搜索" clearable />
|
||||
<ul>
|
||||
<li v-for="(tip, index) in tips" :key="index" @click="selectAddr(tip.location)">
|
||||
<p>{{ tip.name }}</p>
|
||||
@@ -13,9 +13,8 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div slot="footer" class="footer">
|
||||
|
||||
<Button type="primary" :loading="loading" @click="ok">确定</Button>
|
||||
<div class="footer">
|
||||
<el-button type="primary" :loading="loading" @click="ok">确定</el-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,38 +1,50 @@
|
||||
<template>
|
||||
<Modal width="800" footer-hide v-model="enableMap">
|
||||
<RadioGroup @on-change="changeMap" v-model="mapDefault" type="button">
|
||||
<Radio label="select">级联选择</Radio>
|
||||
<Radio label="map" v-if="aMapSwitch">高德地图</Radio>
|
||||
</RadioGroup>
|
||||
<el-dialog v-model="enableMap" width="800px" :show-close="true" destroy-on-close>
|
||||
<el-radio-group v-model="mapDefault" @change="changeMap">
|
||||
<el-radio-button value="select">级联选择</el-radio-button>
|
||||
<el-radio-button v-if="aMapSwitch" value="map">高德地图</el-radio-button>
|
||||
</el-radio-group>
|
||||
<div>
|
||||
<div v-if="mapDefault === 'select'">
|
||||
<div class="selector">
|
||||
<div class="selector-item" v-for="(plant, plantIndex) in Object.keys(data)" :key="plantIndex">
|
||||
<div :class="{ 'active': chiosend[plantIndex].id == item.id }" v-for="(item, index) in data[plant]"
|
||||
<div
|
||||
v-for="(plant, plantIndex) in Object.keys(data)"
|
||||
:key="plantIndex"
|
||||
class="selector-item"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in data[plant]"
|
||||
:key="index"
|
||||
@click="init(item, plantIndex != Object.keys(data).length - 1 ? Object.keys(data)[plantIndex + 1] : 0, plantIndex)"
|
||||
class="map-item">
|
||||
:class="{ active: chiosend[plantIndex]?.id == item.id }"
|
||||
class="map-item"
|
||||
@click="
|
||||
init(
|
||||
item,
|
||||
plantIndex != Object.keys(data).length - 1
|
||||
? Object.keys(data)[plantIndex + 1]
|
||||
: 0,
|
||||
plantIndex
|
||||
)
|
||||
"
|
||||
>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="footer">
|
||||
<Button type="primary" @click="finished">确定</Button>
|
||||
<el-button type="primary" @click="finished">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<mapping v-if="mapDefault === 'map'" ref="map" @getAddress="getAddress" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</Modal>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { aMapSwitch } from '@/config/index'
|
||||
import { aMapSwitch } from "@/config/index";
|
||||
import mapping from "@/components/map/index.vue";
|
||||
import * as API_Setup from "@/api/common.js";
|
||||
|
||||
export default {
|
||||
components: { mapping },
|
||||
data() {
|
||||
@@ -41,87 +53,76 @@ export default {
|
||||
enableMap: false,
|
||||
mapDefault: "select",
|
||||
data: {
|
||||
province: [], //省
|
||||
city: [], //市
|
||||
area: [], //区
|
||||
street: [], //街道
|
||||
province: [],
|
||||
city: [],
|
||||
area: [],
|
||||
street: [],
|
||||
},
|
||||
chiosend: [],
|
||||
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
||||
this.chiosend = new Array(4).fill("");
|
||||
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.enableMap = true
|
||||
this.init({ id: 0 }, 'province');
|
||||
this.enableMap = true;
|
||||
this.init({ id: 0 }, "province");
|
||||
},
|
||||
changeMap(val) {
|
||||
this.mapDefault = val
|
||||
|
||||
|
||||
this.mapDefault = val;
|
||||
},
|
||||
init(val, level = 'province', index) {
|
||||
init(val, level = "province", index) {
|
||||
if (level == 0) {
|
||||
// 说明选择到了街道,将街道id存入数组
|
||||
this.chiosend.splice(3, 1, val);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
API_Setup.getChildRegion(val.id).then((res) => {
|
||||
if (res.result.length && val.id !== 0) {
|
||||
this.chiosend[index] = val
|
||||
}
|
||||
else if(!res.result.length){
|
||||
this.chiosend[index] = val
|
||||
this.chiosend[index] = val;
|
||||
} else if (!res.result.length) {
|
||||
this.chiosend[index] = val;
|
||||
}
|
||||
this.data[level] = res.result;
|
||||
if (level == 'city') {
|
||||
this.data.area = []
|
||||
this.data.street = []
|
||||
this.chiosend.splice(1, 3, "","","");
|
||||
if (level == "city") {
|
||||
this.data.area = [];
|
||||
this.data.street = [];
|
||||
this.chiosend.splice(1, 3, "", "", "");
|
||||
}
|
||||
if (level == 'area') {
|
||||
this.data.street = []
|
||||
this.chiosend.splice(2, 2, "","");
|
||||
if (level == "area") {
|
||||
this.data.street = [];
|
||||
this.chiosend.splice(2, 2, "", "");
|
||||
}
|
||||
if (level == 'street') {
|
||||
if (level == "street") {
|
||||
this.chiosend.splice(3, 1, "");
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
getAddress(center) {
|
||||
this.$emit('callback', {
|
||||
this.$emit("callback", {
|
||||
type: this.mapDefault,
|
||||
data: center
|
||||
})
|
||||
data: center,
|
||||
});
|
||||
this.enableMap = false;
|
||||
},
|
||||
// 选择完成
|
||||
finished() {
|
||||
if(!this.chiosend[0]){
|
||||
this.$Message.error("请选择地址")
|
||||
return
|
||||
if (!this.chiosend[0]) {
|
||||
this.$Message.error("请选择地址");
|
||||
return;
|
||||
}
|
||||
const params = this.chiosend.filter((item) => item!=="" && item.value !== "");
|
||||
const params = this.chiosend.filter((item) => item !== "" && item.value !== "");
|
||||
this.enableMap = false;
|
||||
this.$emit('callback', {
|
||||
this.$emit("callback", {
|
||||
type: this.mapDefault,
|
||||
data: params
|
||||
})
|
||||
data: params,
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selector {
|
||||
|
||||
|
||||
height: 400px;
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
|
||||
58
manager/src/components/price-color-scheme.vue
Normal file
58
manager/src/components/price-color-scheme.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<span :style="priceStyle">
|
||||
{{ dot }}{{ displayText }}
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { unitPrice } from "@/utils/filters";
|
||||
|
||||
export default {
|
||||
name: "priceColorScheme",
|
||||
props: {
|
||||
value: {
|
||||
default: 0,
|
||||
validator(val) {
|
||||
return (
|
||||
val === null ||
|
||||
val === undefined ||
|
||||
typeof val === "number" ||
|
||||
typeof val === "string"
|
||||
);
|
||||
},
|
||||
},
|
||||
unit: {
|
||||
type: String,
|
||||
default: "¥",
|
||||
},
|
||||
dot: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
customStyle: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
displayText() {
|
||||
const val = this.value;
|
||||
if (val === null || val === undefined || val === "" || val === "null") {
|
||||
return `${this.unit || "¥"}0.00`;
|
||||
}
|
||||
return unitPrice(val, this.unit);
|
||||
},
|
||||
priceStyle() {
|
||||
const resolvedColor = this.color || this.$mainColor || "";
|
||||
return resolvedColor
|
||||
? { color: resolvedColor, ...this.customStyle }
|
||||
: { ...this.customStyle };
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,182 +1,149 @@
|
||||
<template>
|
||||
<div>
|
||||
<Cascader
|
||||
:data="data"
|
||||
:load-data="loadData"
|
||||
<el-cascader
|
||||
v-model="addr"
|
||||
:options="data"
|
||||
:props="cascaderProps"
|
||||
placeholder="请选择地址"
|
||||
@on-change="change"
|
||||
style="width: 350px"
|
||||
></Cascader>
|
||||
@change="change"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {getChildRegion} from '@/api/common.js';
|
||||
import { getChildRegion } from "@/api/common.js";
|
||||
|
||||
export default {
|
||||
data () {
|
||||
props: ["addressId"],
|
||||
data() {
|
||||
return {
|
||||
data: [], // 地区数据
|
||||
addr: [] // 已选数据
|
||||
data: [],
|
||||
addr: [],
|
||||
};
|
||||
},
|
||||
props: ['addressId'],
|
||||
mounted () {},
|
||||
computed: {
|
||||
cascaderProps() {
|
||||
return {
|
||||
value: "value",
|
||||
label: "label",
|
||||
lazy: true,
|
||||
lazyLoad: this.loadData,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
change (val, selectedData) { // 选择地区
|
||||
/**
|
||||
* @returns [regionId,region]
|
||||
*/
|
||||
this.$emit('selected', [
|
||||
val,
|
||||
selectedData[selectedData.length - 1].__label.split('/')
|
||||
]);
|
||||
change(val) {
|
||||
if (!val || !val.length) {
|
||||
this.$emit("selected", [[], []]);
|
||||
return;
|
||||
}
|
||||
const labels = this.resolveLabels(val);
|
||||
this.$emit("selected", [val, labels]);
|
||||
},
|
||||
loadData (item, callback) { // 加载数据
|
||||
item.loading = true;
|
||||
getChildRegion(item.value).then((res) => {
|
||||
if (res.result.length <= 0) {
|
||||
item.loading = false;
|
||||
} else {
|
||||
res.result.forEach((child) => {
|
||||
item.loading = false;
|
||||
resolveLabels(values) {
|
||||
const labels = [];
|
||||
let options = this.data;
|
||||
for (const v of values) {
|
||||
const node = options.find((item) => item.value === v);
|
||||
if (!node) break;
|
||||
labels.push(node.label);
|
||||
options = node.children || [];
|
||||
}
|
||||
return labels;
|
||||
},
|
||||
loadData(node, resolve) {
|
||||
const parentId = node.level === 0 ? 0 : node.value;
|
||||
getChildRegion(parentId).then((res) => {
|
||||
if (!res.result || res.result.length <= 0) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
const nodes = res.result.map((child) => {
|
||||
const isLeaf =
|
||||
child.level === "street" ||
|
||||
node.label === "香港特别行政区" ||
|
||||
child.name === "台湾省";
|
||||
return {
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
leaf: isLeaf,
|
||||
};
|
||||
});
|
||||
resolve(nodes);
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
const data = await getChildRegion(0);
|
||||
this.data = data.result.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
leaf: item.name === "台湾省",
|
||||
}));
|
||||
},
|
||||
async reviewData() {
|
||||
const addr = JSON.parse(JSON.stringify(this.addressId.split(",")));
|
||||
const length = addr.length;
|
||||
const root = await getChildRegion(0);
|
||||
const arr0 = root.result.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
leaf: item.name === "台湾省",
|
||||
children: [],
|
||||
}));
|
||||
|
||||
let data = {
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
loading: false,
|
||||
children: []
|
||||
};
|
||||
|
||||
if (child.level === 'street' || item.label === '香港特别行政区') {
|
||||
item.children.push({
|
||||
value: child.id,
|
||||
label: child.name
|
||||
});
|
||||
} else {
|
||||
item.children.push(data);
|
||||
}
|
||||
});
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
async init () { // 初始化地图数据
|
||||
let data = await getChildRegion(0);
|
||||
let arr = [];
|
||||
data.result.forEach((item) => {
|
||||
let obj;
|
||||
// 台湾省做处理
|
||||
if (item.name === '台湾省') {
|
||||
obj = {
|
||||
value: item.id,
|
||||
label: item.name
|
||||
};
|
||||
} else {
|
||||
obj = {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
loading: false,
|
||||
children: []
|
||||
};
|
||||
}
|
||||
arr.push(obj);
|
||||
});
|
||||
this.data = arr;
|
||||
},
|
||||
async reviewData () {
|
||||
// 数据回显
|
||||
let addr = JSON.parse(JSON.stringify(this.addressId.split(',')));
|
||||
let length = addr.length;
|
||||
let data = await getChildRegion(0);
|
||||
let arr0 = [];
|
||||
let arr1 = [];
|
||||
let arr2 = [];
|
||||
// 第一级数据
|
||||
data.result.forEach((item) => {
|
||||
let obj;
|
||||
// 台湾省做处理
|
||||
if (item.name === '台湾省') {
|
||||
obj = {
|
||||
value: item.id,
|
||||
label: item.name
|
||||
};
|
||||
} else {
|
||||
obj = {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
loading: false,
|
||||
children: []
|
||||
};
|
||||
}
|
||||
arr0.push(obj);
|
||||
});
|
||||
// 根据选择的数据来加载数据列表
|
||||
if (length > 0) {
|
||||
let children = await getChildRegion(addr[0]);
|
||||
children = this.handleData(children.result);
|
||||
const children = await getChildRegion(addr[0]);
|
||||
const arr1 = this.handleData(children.result);
|
||||
arr0.forEach((e) => {
|
||||
if (e.value === addr[0]) {
|
||||
e.children = arr1 = children;
|
||||
e.children = arr1;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (length > 1) {
|
||||
let children = await getChildRegion(addr[1]);
|
||||
children = this.handleData(children.result);
|
||||
let arr1 = arr0.find((e) => e.value === addr[0])?.children || [];
|
||||
const children = await getChildRegion(addr[1]);
|
||||
const arr2 = this.handleData(children.result);
|
||||
arr1.forEach((e) => {
|
||||
if (e.value === addr[1]) {
|
||||
e.children = arr2 = children;
|
||||
e.children = arr2;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (length > 2) {
|
||||
let children = await getChildRegion(addr[2]);
|
||||
children = this.handleData(children.result);
|
||||
const arr1 = arr0.find((e) => e.value === addr[0])?.children || [];
|
||||
const arr2 = arr1.find((e) => e.value === addr[1])?.children || [];
|
||||
const children = await getChildRegion(addr[2]);
|
||||
const arr3 = this.handleData(children.result);
|
||||
arr2.forEach((e) => {
|
||||
if (e.value === addr[2]) {
|
||||
e.children = children;
|
||||
e.children = arr3;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.data = arr0;
|
||||
this.addr = addr;
|
||||
},
|
||||
handleData (data) {
|
||||
// 处理接口数据
|
||||
let item = [];
|
||||
data.forEach((child) => {
|
||||
let obj = {
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
loading: false,
|
||||
children: []
|
||||
};
|
||||
|
||||
if (child.level === 'street' || item.label === '香港特别行政区') {
|
||||
item.push({
|
||||
value: child.id,
|
||||
label: child.name
|
||||
});
|
||||
} else {
|
||||
item.push(obj);
|
||||
}
|
||||
});
|
||||
return item;
|
||||
}
|
||||
handleData(data) {
|
||||
return data.map((child) => ({
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
leaf: child.level === "street",
|
||||
children: child.level === "street" ? undefined : [],
|
||||
}));
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
addressId: {
|
||||
handler: function (v) {
|
||||
handler(v) {
|
||||
if (v) {
|
||||
this.reviewData();
|
||||
} else {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<div
|
||||
v-if="columns.length > 0"
|
||||
ref="table"
|
||||
v-loading="loading"
|
||||
:class="[prefixCls, `${prefixCls}-${size}`, tableClass]">
|
||||
<Spin fix v-if="loading"></Spin>
|
||||
<div
|
||||
v-show="showHeader"
|
||||
ref="header-wrapper"
|
||||
@@ -297,6 +297,11 @@ export default {
|
||||
cellStyle: [Object, Function],
|
||||
expandKey: String
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
treeTableRoot: this,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
computedWidth: "",
|
||||
@@ -387,7 +392,7 @@ export default {
|
||||
this.measure();
|
||||
window.addEventListener("resize", this.measure);
|
||||
},
|
||||
beforeDestroy() {
|
||||
beforeUnmount() {
|
||||
window.removeEventListener("resize", this.measure);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
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 },
|
||||
inject: {
|
||||
treeTableRoot: { default: null },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
radioSelectedIndex: -1,
|
||||
@@ -15,6 +15,12 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
table() {
|
||||
if (this.treeTableRoot) return this.treeTableRoot;
|
||||
let parent = this.$parent;
|
||||
while (parent) {
|
||||
if (parent.$options && parent.$options.name === 'TreeTable') return parent;
|
||||
parent = parent.$parent;
|
||||
}
|
||||
return this.$parent;
|
||||
},
|
||||
},
|
||||
@@ -186,8 +192,21 @@ export default {
|
||||
return classList.join(' ');
|
||||
}
|
||||
|
||||
// Vue 3:scoped slot 合并到 $slots
|
||||
function renderTemplateSlot(table, slotName, scope) {
|
||||
if (!table || !slotName) return '';
|
||||
const slots = table.$slots || {};
|
||||
let slot = slots[slotName];
|
||||
if (!slot && table.$scopedSlots && table.$scopedSlots[slotName]) {
|
||||
slot = table.$scopedSlots[slotName];
|
||||
}
|
||||
if (!slot) return '';
|
||||
return slot(scope);
|
||||
}
|
||||
|
||||
// 根据type渲染单元格Cell
|
||||
function renderCell(row, rowIndex, column, columnIndex) {
|
||||
if (!row || !column) return '';
|
||||
// ExpandType
|
||||
if (this.isExpandCell(this.table, columnIndex)) {
|
||||
return <i class='zk-icon zk-icon-angle-right'></i>;
|
||||
@@ -226,7 +245,15 @@ export default {
|
||||
// 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>;
|
||||
res = (
|
||||
<input
|
||||
type="radio"
|
||||
checked={this.radioSelectedIndex === rowIndex}
|
||||
onChange={() =>
|
||||
this.handleEvent(null, 'radio', { row, rowIndex, column, columnIndex })
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -254,9 +281,12 @@ export default {
|
||||
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 renderTemplateSlot.call(this, this.table, column.template, {
|
||||
row,
|
||||
rowIndex,
|
||||
column,
|
||||
columnIndex,
|
||||
});
|
||||
}
|
||||
return '';
|
||||
}
|
||||
@@ -305,10 +335,7 @@ export default {
|
||||
<td
|
||||
class={`${this.prefixCls}--expand-content`}
|
||||
colspan={this.table.tableColumns.length}>
|
||||
{this.table.$scopedSlots.expand
|
||||
? this.table.$scopedSlots.expand({ row, rowIndex })
|
||||
: ''
|
||||
}
|
||||
{renderTemplateSlot.call(this, this.table, 'expand', { row, rowIndex })}
|
||||
</td>
|
||||
</tr>,
|
||||
])
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
let scrollBarWidth;
|
||||
|
||||
export default function () {
|
||||
if (Vue.prototype.$isServer) return 0;
|
||||
export default function getScrollBarWidth() {
|
||||
if (typeof document === "undefined") 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';
|
||||
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';
|
||||
outer.style.overflow = "scroll";
|
||||
|
||||
const inner = document.createElement('div');
|
||||
inner.style.width = '100%';
|
||||
const inner = document.createElement("div");
|
||||
inner.style.width = "100%";
|
||||
outer.appendChild(inner);
|
||||
|
||||
const widthWithScroll = inner.offsetWidth;
|
||||
|
||||
@@ -1,59 +1,81 @@
|
||||
<template>
|
||||
<div class="verify-content" v-if="show" @mousemove="mouseMove" @mouseup="mouseUp" @click.stop>
|
||||
<div class="imgBox" :style="{width:data.originalWidth+'px',height:data.originalHeight + 'px'}">
|
||||
<img :src="data.backImage" style="width:100%;height:100%" alt="">
|
||||
<img class="slider" :src="data.slidingImage" :style="{left:distance+'px',top:data.randomY+'px'}" :width="data.sliderWidth" :height="data.sliderHeight" alt="">
|
||||
<Icon type="md-refresh" class="refresh" @click="init" />
|
||||
<div
|
||||
class="verify-content"
|
||||
v-if="show"
|
||||
@mousemove="mouseMove"
|
||||
@mouseup="mouseUp"
|
||||
@click.stop
|
||||
>
|
||||
<div
|
||||
class="imgBox"
|
||||
:style="{
|
||||
width: data.originalWidth + 'px',
|
||||
height: data.originalHeight + 'px',
|
||||
}"
|
||||
>
|
||||
<img :src="data.backImage" style="width: 100%; height: 100%" alt="" />
|
||||
<img
|
||||
class="slider"
|
||||
:src="data.slidingImage"
|
||||
:style="{ left: distance + 'px', top: data.randomY + 'px' }"
|
||||
:width="data.sliderWidth"
|
||||
:height="data.sliderHeight"
|
||||
alt=""
|
||||
/>
|
||||
<el-icon class="refresh" @click="init"><Refresh /></el-icon>
|
||||
</div>
|
||||
<div class="handle" :style="{width:data.originalWidth+'px'}">
|
||||
<span class="bgcolor" :style="{width:distance + 'px',background:bgColor}"></span>
|
||||
<span class="swiper" :style="{left:distance + 'px'}" @mousedown="mouseDown">
|
||||
<Icon type="md-arrow-round-forward" />
|
||||
<div class="handle" :style="{ width: data.originalWidth + 'px' }">
|
||||
<span
|
||||
class="bgcolor"
|
||||
:style="{ width: distance + 'px', background: bgColor }"
|
||||
></span>
|
||||
<span class="swiper" :style="{ left: distance + 'px' }" @mousedown="mouseDown">
|
||||
<el-icon><DArrowRight /></el-icon>
|
||||
</span>
|
||||
<span class="text">{{verifyText}}</span>
|
||||
<span class="text">{{ verifyText }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getVerifyImg, postVerifyImg } from './verify.js';
|
||||
import { Refresh, DArrowRight } from "@element-plus/icons-vue";
|
||||
import { getVerifyImg, postVerifyImg } from "./verify.js";
|
||||
|
||||
export default {
|
||||
components: { Refresh, DArrowRight },
|
||||
props: {
|
||||
// 传入数据,判断是登录、注册、修改密码
|
||||
verifyType: {
|
||||
defalut: 'LOGIN',
|
||||
type: String
|
||||
}
|
||||
default: "LOGIN",
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
show: false, // 验证码显隐
|
||||
type: 'LOGIN', // 请求类型
|
||||
data: { // 验证码数据
|
||||
backImage: '',
|
||||
slidingImage: '',
|
||||
show: false,
|
||||
type: "LOGIN",
|
||||
data: {
|
||||
backImage: "",
|
||||
slidingImage: "",
|
||||
originalHeight: 150,
|
||||
originalWidth: 300,
|
||||
sliderWidth: 60,
|
||||
sliderHeight: 60
|
||||
sliderHeight: 60,
|
||||
},
|
||||
distance: 0, // 拼图移动距离
|
||||
flag: false, // 判断滑块是否按下
|
||||
downX: 0, // 鼠标按下位置
|
||||
bgColor: '#04ad11', // 滑动背景颜色
|
||||
verifyText: '拖动滑块解锁' // 文字提示
|
||||
distance: 0,
|
||||
flag: false,
|
||||
downX: 0,
|
||||
bgColor: "#04ad11",
|
||||
verifyText: "拖动滑块解锁",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 鼠标按下事件,开始拖动滑块
|
||||
mouseDown (e) {
|
||||
mouseDown(e) {
|
||||
this.downX = e.clientX;
|
||||
this.flag = true;
|
||||
},
|
||||
// 鼠标移动事件,计算距离
|
||||
mouseMove (e) {
|
||||
mouseMove(e) {
|
||||
if (this.flag) {
|
||||
let offset = e.clientX - this.downX;
|
||||
|
||||
const offset = e.clientX - this.downX;
|
||||
if (offset > this.data.originalWidth - 43) {
|
||||
this.distance = this.data.originalWidth - 43;
|
||||
} else if (offset < 0) {
|
||||
@@ -63,65 +85,63 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
// 鼠标抬起事件,验证是否正确
|
||||
mouseUp () {
|
||||
mouseUp() {
|
||||
if (!this.flag) return false;
|
||||
this.flag = false;
|
||||
let params = {
|
||||
const params = {
|
||||
verificationEnums: this.type,
|
||||
xPos: this.distance
|
||||
xPos: this.distance,
|
||||
};
|
||||
postVerifyImg(params).then(res => {
|
||||
if (res.success) {
|
||||
if (res.result) {
|
||||
this.bgColor = 'green';
|
||||
this.verifyText = '解锁成功';
|
||||
this.$emit('change', { status: true, distance: this.distance });
|
||||
postVerifyImg(params)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
if (res.result) {
|
||||
this.bgColor = "green";
|
||||
this.verifyText = "解锁成功";
|
||||
this.$emit("change", { status: true, distance: this.distance });
|
||||
} else {
|
||||
this.bgColor = "red";
|
||||
this.verifyText = "解锁失败";
|
||||
setTimeout(() => this.init(), 1000);
|
||||
this.$emit("change", { status: false, distance: this.distance });
|
||||
}
|
||||
} else {
|
||||
this.bgColor = 'red';
|
||||
this.verifyText = '解锁失败';
|
||||
let that = this;
|
||||
setTimeout(() => {
|
||||
that.init();
|
||||
}, 1000);
|
||||
this.$emit('change', { status: false, distance: this.distance });
|
||||
this.init();
|
||||
}
|
||||
} else {
|
||||
this.init()
|
||||
}
|
||||
|
||||
}).catch(()=>{
|
||||
this.init()
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
this.init();
|
||||
});
|
||||
},
|
||||
init () { // 初始化数据
|
||||
init() {
|
||||
this.flag = false;
|
||||
this.downX = 0;
|
||||
this.distance = 0;
|
||||
this.bgColor = '#04ad11';
|
||||
this.verifyText = '拖动滑块解锁';
|
||||
getVerifyImg(this.type).then(res => {
|
||||
this.bgColor = "#04ad11";
|
||||
this.verifyText = "拖动滑块解锁";
|
||||
getVerifyImg(this.type).then((res) => {
|
||||
if (res.result) {
|
||||
this.data = res.result;
|
||||
this.show = true;
|
||||
} else {
|
||||
this.$Message.warning('请求失败请重试!')
|
||||
this.$Message.warning("请求失败请重试!");
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
verifyType: {
|
||||
immediate: true,
|
||||
handler: function (v) {
|
||||
handler(v) {
|
||||
this.type = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.verify-content{
|
||||
.verify-content {
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
border: 1px solid #eee;
|
||||
@@ -174,9 +194,7 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.ivu-icon {
|
||||
font-size: 20px;
|
||||
}
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.text {
|
||||
|
||||
Reference in New Issue
Block a user