组件拆分

This commit is contained in:
huangjinming 2022-12-05 13:44:18 +08:00
parent 315dcaf870
commit 552ceda11a
11 changed files with 1068 additions and 378 deletions

View File

@ -1,22 +1,22 @@
module.exports = {
plugins: {
autoprefixer: {}, // 用来给不同的浏览器自动添加相应前缀,如-webkit--moz-等等
"postcss-px-to-viewport": {
unitToConvert: "px", // 要转化的单位
viewportWidth: 1080, // UI设计稿的宽度
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ["*"], // 指定转换的css属性的单位*代表全部css属性的单位都进行转换
viewportUnit: "vw", // 指定需要转换成的视窗单位默认vw
fontViewportUnit: "vw", // 指定字体需要转换成的视窗单位默认vw
selectorBlackList: ["wrap"], // 指定不转换为视窗单位的类名,
minPixelValue: 1, // 默认值1小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换默认false
replace: true, // 是否转换后直接更换属性值
exclude: [/\/src\/views\/desktop\//], // 设置忽略文件,用正则做目录名匹配
landscape: false // 是否处理横屏情况
},
// module.exports = {
// plugins: {
// autoprefixer: {}, // 用来给不同的浏览器自动添加相应前缀,如-webkit--moz-等等
// "postcss-px-to-viewport": {
// unitToConvert: "px", // 要转化的单位
// viewportWidth: 1080, // UI设计稿的宽度
// unitPrecision: 6, // 转换后的精度,即小数点位数
// propList: ["*"], // 指定转换的css属性的单位*代表全部css属性的单位都进行转换
// viewportUnit: "vw", // 指定需要转换成的视窗单位默认vw
// fontViewportUnit: "vw", // 指定字体需要转换成的视窗单位默认vw
// selectorBlackList: ["wrap"], // 指定不转换为视窗单位的类名,
// minPixelValue: 1, // 默认值1小于或等于1px则不进行转换
// mediaQuery: true, // 是否在媒体查询的css代码中也进行转换默认false
// replace: true, // 是否转换后直接更换属性值
// exclude: [/\/src\/views\/desktop\//], // 设置忽略文件,用正则做目录名匹配
// landscape: false // 是否处理横屏情况
// },
}
};
// }
// };

View File

@ -1,8 +1,8 @@
<template>
<div class="container">
<Herofilter @searchClear="searchClear" :value="value" v-if="nftType - 1 == 0" ></Herofilter>
<Weaponfilter v-else-if="nftType - 1 == 1"></Weaponfilter>
<Chipfilter v-else-if="nftType - 1 == 2"></Chipfilter>
<Herofilter @searchClear="searchClear" :isType="isType" :value="value" v-if="nftType - 1 == 0" ></Herofilter>
<Weaponfilter v-else-if="nftType - 1 == 1" :isType="isType"></Weaponfilter>
<Chipfilter v-else-if="nftType - 1 == 2" :isType="isType"></Chipfilter>
</div>
</template>
@ -11,7 +11,7 @@ import Herofilter from "@/components/market/filters/Herofilter";
import Weaponfilter from "@/components/market/filters/Weaponfilter";
import Chipfilter from "@/components/market/filters/Chipfilter";
export default {
props: ["nftType","value"],
props: ["nftType","value",'isType'],
components: {
Herofilter,
Chipfilter,

View File

@ -0,0 +1,101 @@
<template>
<div>
<div class="price">
<div class="price-btn" @click="priceFilter">Price</div>
<div class="price-bottom">
<div class="price-min">
<el-input
v-model="priceMin"
:maxlength="13"
placeholder="Min"
></el-input>
</div>
<div class="boder"></div>
<div class="price-max">
<el-input
v-model="priceMax"
:maxlength="13"
placeholder="Max"
></el-input>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "",
props: ["priceMin", "priceMax"],
methods: {
priceFilter(){
}
},
};
</script>
<style lang="scss" scoped>
.price {
// margin-top: 177px;
margin-left: 23px;
display: flex;
flex-direction: column;
// align-items: center;
.price-btn {
width: 124px;
font-size: 24px;
font-weight: normal;
text-align: center;
cursor: pointer;
color: #ffffff;
height: 47px;
margin-left: 85px;
margin-bottom: 24px;
line-height: 47px;
background: url("../../assets/market/filter-left/btn-bg.png") no-repeat;
}
.price-min {
width: 124px;
font-size: 24px;
font-weight: normal;
text-align: center;
color: #ffffff;
height: 34px;
background: url("../../assets/market/filter-left/price-btn.png") no-repeat;
background-size: 100% 100%;
}
.price-max {
width: 124px;
font-size: 24px;
font-weight: normal;
text-align: center;
color: #ffffff;
height: 34px;
background: url("../../assets/market/filter-left/price-btn.png") no-repeat;
background-size: 100% 100%;
}
.price-bottom {
display: flex;
width: 290px;
justify-content: flex-start;
::v-deep .el-input__inner {
background: transparent;
height: 34px;
color: #fff;
border: none;
}
::v-deep .el-input__inner::placeholder {
color: #fff;
text-align: center;
}
}
.boder {
margin-top: 15px;
width: 20px;
margin-right: 11px;
margin-left: 11px;
background: #ffffff;
height: 2px;
}
}
</style>

View File

@ -0,0 +1,119 @@
<template>
<div>
<div class="attributes">
<el-select
class="se"
v-model="value"
:popper-append-to-body="false"
@change="handSelect"
placeholder="请选择"
popper-class="select-popper"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
</div>
</template>
<script>
export default {
props:['value','options'],
methods:{
handSelect(){
}
}
}
</script>
<style lang="scss" scoped>
$item-bg-color: rgba(21, 158, 175, 0.7);
$item-size: 20px;
.attributes {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 86px;
.se {
width: 200px;
}
}
::v-deep .el-input--suffix .el-input__inner {
width: 200px;
height: 36px;
font-size: 23px;
border: none;
text-align: center;
color: #fff;
background: rgba(21, 158, 175, 1);
border-radius: 18px;
}
::v-deep .el-select .el-input .el-select__caret.el-input__icon::before {
content: "";
background: url("../../assets/market/filter-left/select-icon.png") center
center no-repeat;
color: #fd724e;
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
::v-deep .el-input__inner {
&::placeholder {
text-align: center;
}
}
// .el-select .el-input .el-select__caret {
// transform: rotateZ(0deg);
// }
::v-deep .select-popper {
background-color: $item-bg-color;
border-radius: 0.08rem;
border: solid 0.02rem $item-bg-color;
border-radius: 18px;
font-family: "PingFangSC-Regular";
.el-select-dropdown__item.selected {
font-family: "PingFangSC-Regular";
font-size: $item-size;
border-radius: 18px;
color: rgb(16, 17, 17);
}
li {
color: #fff;
background: transparent;
color: #fff;
text-align: center;
border-radius: 18px;
font-size: $item-size;
}
.el-select-dropdown__item:hover,
.el-select-dropdown__item.hover {
background: rgba(21, 158, 175, 1);
margin-right: 1px;
}
.popper__arrow::after {
border-bottom-color: $item-bg-color;
}
.popper__arrow {
border-bottom-color: $item-bg-color;
}
.el-select-dropdown__empty {
padding: 0.2rem;
font-size: $item-size;
}
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<div>
<div class="search-content">
<div class="search-input">
<el-input
prefix-icon="el-icon-search"
v-model="hero"
:maxlength="24"
:autofocus="true"
placeholder="Search Name or Tokenid"
></el-input>
</div>
<div class="search-btn" @click="searchClear"></div>
</div>
</div>
</template>
<script>
export default {
name: "SearchInput",
props: ["hero"],
methods: {
searchClear() {
this.$emit("searchClear", this.hero);
},
},
};
</script>
<style lang="scss" scoped>
.search-content {
display: flex;
margin-top: 40px;
margin-left: 11px;
.search-input {
width: 216px;
height: 34px;
background: url("../../assets/market/filter-left/search-input.png")
no-repeat;
}
.search-btn {
width: 96px;
margin-left: 5px;
height: 34px;
cursor: pointer;
background: url("../../assets/market/filter-left/search-clear.png")
no-repeat;
}
.search-input {
::v-deep .el-input__inner {
height: 34px;
border-top-left-radius: 14px;
border-bottom-left-radius: 14px;
border: none;
color: #6a6f77;
outline: 0;
}
::v-deep .el-input__icon {
line-height: 33px !important;
}
}
}
</style>

View File

@ -4,7 +4,8 @@
<div class="thunk" ref="trunk" :style="{ left }">
<div class="block"></div>
<div class="tips">
<span>{{ scale * 15 }}</span>
<!-- <span>{{ max === 100 ? parseInt(scale * 100) + "%" : scale * max }}</span> -->
<span>{{curValue}}</span>
<i class="fas fa-caret-down"></i>
</div>
</div>
@ -52,6 +53,11 @@ export default {
return false;
};
},
watch: {
curValue(newVal, old) {
this.$emit("onChange", newVal);
},
},
computed: {
// slidertrunkleft
// -/- = sliderwidth / sliderwidth
@ -59,6 +65,9 @@ export default {
scale() {
return (this.per - this.min) / (this.max - this.min);
},
curValue(){
return this.max === 100 ? parseInt(this.scale * this.max) + "%" : this.scale * this.max
},
width() {
if (this.slider) {
return this.slider.offsetWidth * this.scale + "px";

View File

@ -1,22 +1,230 @@
<template>
<div class="container">
3
<div class="container">
<div class="filter"></div>
<SearchInput :hero="hero" @searchClear="searchClear" />
<PropertySelect
:value="value"
:options="options"
@handSelect="handSelect"
/>
<div class="job-content">
<div class="job">
<img
width="116px"
src="../../../assets/market/filter-left/job.png"
alt=""
/>
</div>
<div class="job-options">
<div class="job-item" v-for="(item, i) in jobList" :key="i">
<div @click="jobStatus(item)">
<img
width="66px"
v-if="item.jobType === true"
:src="item.jobImg"
alt=""
/>
<img width="66px" v-else :src="item.disImg" alt="" />
</div>
</div>
</div>
</div>
<div class="level-filter">
<div class="level-item">
<div class="btn-bg">Quility</div>
<div class="level-slider">
<div>
<Slider
:max="15"
@sliderChange="sliderChange"
:min="0"
:value="value"
></Slider>
</div>
<div class="slider-number">
<div>0</div>
<div>15</div>
</div>
</div>
</div>
</div>
<PriceFilter
v-show="isType !=='mynft'"
@priceFilter="priceFilter"
:priceMin="priceMin"
:priceMax="priceMax"
/>
</div>
</template>
<script>
import Slider from "../Slider.vue";
import SearchInput from "../SearchInput";
import PriceFilter from "../PriceFilter.vue";
import PropertySelect from "../PropertySelect.vue";
export default {
props: ["value",'isType'],
components: {
Slider,
SearchInput,
PriceFilter,
PropertySelect,
},
data() {
return {
hero: "",
priceMin: "",
priceMax: "",
jobList: [
{
id: 0,
jobname: "raider",
jobType: false,
jobImg: require("../../../assets/market/filter-left/raider.png"),
disImg: require("../../../assets/market/filter-left/raider-disabled.png"),
},
{
id: 1,
jobname: "guardian",
jobType: true,
jobImg: require("../../../assets/market/filter-left/guardian.png"),
disImg: require("../../../assets/market/filter-left/guardian-disabled.png"),
},
{
id: 2,
jobname: "machinist",
jobType: true,
jobImg: require("../../../assets/market/filter-left/machinist.png"),
disImg: require("../../../assets/market/filter-left/machinist-disabled.png"),
},
{
id: 3,
jobname: "medic",
jobType: true,
jobImg: require("../../../assets/market/filter-left/medic.png"),
disImg: require("../../../assets/market/filter-left/medic-disabled.png"),
},
],
options: [
{
value: "选项1",
label: "Lowest",
},
{
value: "选项2",
label: "Lowest",
},
{
value: "选项3",
label: "Highest",
},
{
value: "选项4",
label: "Quaility",
},
{
value: "选项5",
label: "Level",
},
],
};
},
}
methods: {
jobStatus(item) {
this.jobList[item.id].jobType = !this.jobList[item.id].jobType;
},
searchClear() {
// this.hero = "";
this.$emit("searchClear", this.hero);
},
sliderChange() {
this.$emit("sliderChange", value);
},
priceFilter() {
this.priceMin = "";
this.priceMax = "";
},
handSelect(value) {
console.log(value);
this.$emit("handSelect", value);
},
},
};
</script>
<style lang="scss" scoped>
$item-bg-color: rgba(21, 158, 175, 0.7);
$item-size: 20px;
.container {
width: 340px;
height: 1170px;
height: 1170px;
margin-top: 49px;
margin-left: 41px;
margin-bottom: 14px;
background: rgba(255, 255, 255, 0.2);
border-radius: 30px;
.filter {
width: 308px;
margin-top: 16px;
margin-left: 16px;
height: 58px;
background: url("../../../assets/market/filter-left/filter-bg.png")
no-repeat;
background-size: 100% 100%;
}
.job-content {
// margin-top: 45px;
display: flex;
margin-left: 15px;
margin-right: 19px;
flex-direction: column;
justify-content: center;
.job {
text-align: center;
cursor: pointer;
}
.job-options {
display: flex;
margin-top: 21px;
justify-content: space-between;
.job-item {
cursor: pointer;
}
}
}
.level-filter {
margin-left: 21px;
margin-right: 22px;
margin-top: 56px;
.level-item {
display: flex;
flex-direction: column;
color: #fff;
}
.level-slider {
display: flex;
flex-direction: column;
align-items: center;
}
.btn-bg {
width: 114px;
margin: 0 auto;
cursor: pointer;
text-align: center;
margin-bottom: 10px;
line-height: 48px;
height: 48px;
background: url("../../../assets/market/filter-left/btn-bg.png") no-repeat;
}
.slider-number {
width: 100%;
display: flex;
justify-content: space-between;
}
}
}
</style>
</style>

View File

@ -1,18 +1,8 @@
<template>
<div class="container">
<div class="filter"></div>
<div class="search-content">
<div class="search-input">
<el-input
prefix-icon="el-icon-search"
v-model="hero"
:maxlength="24"
placeholder="Search Name or Tokenid"
></el-input>
</div>
<div class="search-btn" @click="searchClear"></div>
</div>
<div class="seach-input"></div>
<SearchInput :hero="hero" @searchClear="searchClear"/>
<PropertySelect :value="value" :options="options" @handSelect="handSelect" />
<div class="job-content">
<div class="job">
<img
@ -39,61 +29,72 @@
<div class="level-item">
<div class="btn-bg">Quility</div>
<div class="level-slider">
<div><Slider :max="15" @sliderChange="sliderChange" :min="0" :value="value"></Slider></div>
<div>
<Slider
:max="15"
@onChange="onChange"
:min="0"
:value="value"
></Slider>
</div>
<div class="slider-number">
<div>0</div>
<div>15</div>
</div>
</div>
</div>
<div class="level-item">
<div class="btn-bg">3</div>
<div class="level-slider">
<div><Slider :max="20" :min="0" :value="7"></Slider></div>
<div class="slider-number">
<div>0</div>
<div>20</div>
</div>
</div>
</div>
<div class="level-item">
<div class="btn-bg">2</div>
<div class="level-slider">
<div><Slider :max="15" :min="0" :value="7"></Slider></div>
<div class="slider-number">
<div>0</div>
<div>15</div>
<div>
<Slider
:max="100"
:min="0"
:value="0"
@onChange="levelonChange"
></Slider>
</div>
</div>
</div>
<div class="level-item">
<div class="btn-bg">3</div>
<div class="level-slider">
<div><Slider :max="15" :min="0" :value="7"></Slider></div>
<div class="slider-number">
<div>0</div>
<div>15</div>
<div>100%</div>
</div>
</div>
</div>
</div>
<div class="price">
<div class="price-btn" @click="priceFilter">Price</div>
<div class="price-bottom">
<div class="price-min">
<el-input v-model="priceMin" :maxlength="13" placeholder="Min"></el-input>
</div>
<div class="boder"></div>
<div class="price-max">
<el-input v-model="priceMax" :maxlength="13" placeholder="Max"></el-input>
</div>
</div>
</div>
<PriceFilter v-show="isType !=='mynft'" @priceFilter="priceFilter" :priceMin="priceMin" :priceMax="priceMax" />
</div>
</template>
<script>
import Slider from "../../market/Slider.vue";
import Slider from "../Slider.vue";
import SearchInput from "../SearchInput";
import PriceFilter from "../PriceFilter.vue";
import PropertySelect from "../PropertySelect.vue";
export default {
props: ["value"],
props: ["value",'isType'],
components: {
Slider,
PriceFilter,
SearchInput,
PropertySelect
},
data() {
return {
hero: "",
priceMin:'',
priceMax:'',
priceMin: "",
priceMax: "",
jobList: [
{
id: 0,
@ -124,28 +125,75 @@ export default {
disImg: require("../../../assets/market/filter-left/medic-disabled.png"),
},
],
options: [
{
value: "选项1",
label: "All",
},
{
value: "选项2",
label: "Hill",
},
{
value: "选项3",
label: "Highest",
},
{
value: "选项4",
label: "Yamato",
},
{
value: "选项5",
label: "Miffy",
},
{
value: "选项6",
label: "Canoe",
},
{
value: "选项7",
label: "Mariana",
},
{
value: "选项8",
label: "Lazer",
},
],
};
},
methods: {
jobStatus(item) {
this.jobList[item.id].jobType = !this.jobList[item.id].jobType;
},
searchClear() {
searchClear(hero) {
// this.hero = "";
this.$emit('searchClear',this.hero)
this.$emit("searchClear", hero);
},
sliderChange(){
this.$emit('sliderChange',value)
sliderChange() {
this.$emit("sliderChange", value);
},
priceFilter() {
this.priceMin = "";
this.priceMax = "";
},
handSelect(value) {
console.log(value);
this.$emit("handSelect", value);
},
onChange(newVal) {
console.log(newVal, "scale");
},
levelonChange(newVal2) {
console.log(newVal2, "scale2");
},
priceFilter(){
this.priceMin = "";
this.priceMax = "";
}
},
};
</script>
<style lang="scss" scoped>
$item-bg-color: rgba(21, 158, 175, 0.7);
$item-size: 20px;
.container {
width: 340px;
height: 1170px;
@ -163,27 +211,9 @@ export default {
no-repeat;
background-size: 100% 100%;
}
.search-content {
display: flex;
margin-top: 40px;
margin-left: 11px;
.search-input {
width: 216px;
height: 34px;
background: url("../../../assets/market/filter-left/search-input.png")
no-repeat;
}
.search-btn {
width: 96px;
margin-left: 5px;
height: 34px;
cursor: pointer;
background: url("../../../assets/market/filter-left/search-clear.png")
no-repeat;
}
}
.job-content {
margin-top: 45px;
// margin-top: 45px;
display: flex;
margin-left: 15px;
margin-right: 19px;
@ -232,83 +262,7 @@ export default {
justify-content: space-between;
}
}
.price {
margin-top: 216px;
margin-left: 23px;
display: flex;
flex-direction: column;
// align-items: center;
.price-btn {
width: 124px;
font-size: 24px;
font-weight: normal;
text-align: center;
cursor: pointer;
color: #ffffff;
height: 47px;
margin-left: 85px;
margin-bottom: 24px;
line-height: 47px;
background: url("../../../assets/market/filter-left/btn-bg.png") no-repeat;
}
.price-min {
width: 124px;
font-size: 24px;
font-weight: normal;
text-align: center;
color: #ffffff;
height: 34px;
background: url("../../../assets/market/filter-left/price-btn.png")
no-repeat;
background-size: 100% 100%;
}
.price-max {
width: 124px;
font-size: 24px;
font-weight: normal;
text-align: center;
color: #ffffff;
height: 34px;
background: url("../../../assets/market/filter-left/price-btn.png")
no-repeat;
background-size: 100% 100%;
}
.price-bottom {
display: flex;
width: 290px;
justify-content: flex-start;
::v-deep .el-input__inner {
background: transparent;
height: 34px;
color: #fff;
border: none;
}
::v-deep .el-input__inner::placeholder {
color: #fff;
text-align: center;
}
}
.boder {
margin-top: 15px;
width: 20px;
margin-right: 11px;
margin-left: 11px;
background: #ffffff;
height: 2px;
}
}
}
.search-input {
::v-deep .el-input__inner {
height: 34px;
border-top-left-radius: 14px;
border-bottom-left-radius: 14px;
border: none;
color: #6a6f77;
outline: 0;
}
::v-deep .el-input__icon {
line-height: 33px !important;
}
}
</style>

View File

@ -1,22 +1,228 @@
<template>
<div class="container">
2
<div class="container">
<div class="filter"></div>
<SearchInput :hero="hero" @searchClear="searchClear" />
<PropertySelect
:value="value"
:options="options"
@handSelect="handSelect"
/>
<div class="level-filter">
<div class="level-item">
<div class="btn-bg">Quility</div>
<div class="level-slider">
<div>
<Slider
:max="15"
@sliderChange="sliderChange"
:min="0"
:value="value"
></Slider>
</div>
<div class="slider-number">
<div>0</div>
<div>15</div>
</div>
</div>
</div>
<div class="level-item">
<div class="btn-bg">2</div>
<div class="level-slider">
<div><Slider :max="20" :min="0" :value="7"></Slider></div>
<div class="slider-number">
<div>0</div>
<div>20</div>
</div>
</div>
</div>
<div class="level-item">
<div class="btn-bg">3</div>
<div class="level-slider">
<div><Slider :max="100" :min="0" :value="7"></Slider></div>
<div class="slider-number">
<div>0</div>
<div>100%</div>
</div>
</div>
</div>
</div>
<PriceFilter
v-show="isType !=='mynft'"
@priceFilter="priceFilter"
:priceMin="priceMin"
:priceMax="priceMax"
/>
</div>
</template>
<script>
import Slider from "../Slider.vue";
import SearchInput from "../SearchInput";
import PriceFilter from "../PriceFilter.vue";
import PropertySelect from "../PropertySelect.vue";
export default {
props: ["value",,'isType'],
components: {
SearchInput,
Slider,
PriceFilter,
PropertySelect,
},
data() {
return {
hero: "",
priceMin: "",
priceMax: "",
jobList: [
{
id: 0,
jobname: "raider",
jobType: false,
jobImg: require("../../../assets/market/filter-left/raider.png"),
disImg: require("../../../assets/market/filter-left/raider-disabled.png"),
},
{
id: 1,
jobname: "guardian",
jobType: true,
jobImg: require("../../../assets/market/filter-left/guardian.png"),
disImg: require("../../../assets/market/filter-left/guardian-disabled.png"),
},
{
id: 2,
jobname: "machinist",
jobType: true,
jobImg: require("../../../assets/market/filter-left/machinist.png"),
disImg: require("../../../assets/market/filter-left/machinist-disabled.png"),
},
{
id: 3,
jobname: "medic",
jobType: true,
jobImg: require("../../../assets/market/filter-left/medic.png"),
disImg: require("../../../assets/market/filter-left/medic-disabled.png"),
},
],
options: [
{
value: "选项1",
label: "Lowest",
},
{
value: "选项2",
label: "Lowest",
},
{
value: "选项3",
label: "Highest",
},
{
value: "选项4",
label: "Quaility",
},
{
value: "选项5",
label: "Level",
},
],
};
},
}
methods: {
jobStatus(item) {
this.jobList[item.id].jobType = !this.jobList[item.id].jobType;
},
searchClear() {
// this.hero = "";
this.$emit("searchClear", this.hero);
},
sliderChange() {
this.$emit("sliderChange", value);
},
priceFilter() {
this.priceMin = "";
this.priceMax = "";
},
handSelect(value) {
console.log(value);
this.$emit("handSelect", value);
},
},
};
</script>
<style lang="scss" scoped>
$item-bg-color: rgba(21, 158, 175, 0.7);
$item-size: 20px;
.container {
width: 340px;
height: 1170px;
margin-top: 49px;
margin-left: 41px;
margin-bottom: 14px;
background: rgba(255, 255, 255, 0.2);
border-radius: 30px;
.filter {
width: 308px;
margin-top: 16px;
margin-left: 16px;
height: 58px;
background: url("../../../assets/market/filter-left/filter-bg.png")
no-repeat;
background-size: 100% 100%;
}
.job-content {
// margin-top: 45px;
display: flex;
margin-left: 15px;
margin-right: 19px;
flex-direction: column;
justify-content: center;
.job {
text-align: center;
cursor: pointer;
}
.job-options {
display: flex;
margin-top: 21px;
justify-content: space-between;
.job-item {
cursor: pointer;
}
}
}
.level-filter {
margin-left: 21px;
margin-right: 22px;
margin-top: 56px;
.level-item {
display: flex;
flex-direction: column;
color: #fff;
}
.level-slider {
display: flex;
flex-direction: column;
align-items: center;
}
.btn-bg {
width: 114px;
margin: 0 auto;
cursor: pointer;
text-align: center;
margin-bottom: 10px;
line-height: 48px;
height: 48px;
background: url("../../../assets/market/filter-left/btn-bg.png") no-repeat;
}
.slider-number {
width: 100%;
display: flex;
justify-content: space-between;
}
}
}
</style>
</style>

View File

@ -85,7 +85,7 @@ export default class Market extends Vue {
display: flex;
flex-direction: column;
// align-items: center;
background-image: url(../../assets/market/bg.png.png);
background-image: url('../../assets/market/bg.png.png');
}
.container {
display: flex;

View File

@ -3,32 +3,58 @@
<top-menu class="desk-top" :current-tab="currentTab"></top-menu>
<section class="mynft">
<div class="container">
<div class="wrapper">
<nft-type-bar :select-idx="nftType" @nft-type-changed="onNftTypeClicked" class="left-bar"></nft-type-bar>
<sort-select
<FilterLeft
@filter-show="showFilter"
@searchClear="searchClear"
@sliderChange="sliderChange"
:nft-type="nftType"
:isType="currentTab"
:value="value"
></FilterLeft>
<div class="right-part">
<nft-type-bar
:select-idx="nftType"
@nft-type-changed="onNftTypeClicked"
class="left-bar"
></nft-type-bar>
<!-- <sort-select
:filters="filters"
:selected-index="nftState"
@filter-change="filterChange"
></sort-select>
></sort-select> -->
<!-- <nft-list
:nft-datas="nftList"
v-if="nftList.length > 0"
@activate-clicked="onActivateClick"
></nft-list> -->
<search-result
@filter-show="showFilter"
:select-idx="nftType"
:show-sort="true"
></search-result>
<result-no
v-if="nftList.length === 0"
title="No Record."
desc=""
></result-no>
<pagination
v-if="totalPage > 1"
:total="totalPage"
:current="currentPage"
@to-page="toPage"
class="page-comp"
></pagination>
</div>
<div class="order-status" v-show="showOrderStatus">
<el-tooltip
class="item"
effect="light"
content="Transaction in progress"
placement="right"
>
<time-loader></time-loader>
</el-tooltip>
</div>
<nft-list :nft-datas="nftList" v-if="nftList.length > 0" @activate-clicked="onActivateClick"></nft-list>
<result-no
v-if="nftList.length === 0"
title="No Record."
desc=""
></result-no>
<pagination
v-if="totalPage>1"
:total="totalPage"
:current="currentPage"
@to-page="toPage"
class="page-comp"
></pagination>
</div>
<div class="order-status" v-show="showOrderStatus">
<el-tooltip class="item" effect="light" content="Transaction in progress" placement="right">
<time-loader></time-loader>
</el-tooltip>
</div>
</section>
<base-footer :auto-size="true">></base-footer>
@ -36,29 +62,30 @@
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import SearchPanel from '@/components/market/SearchPanel.vue'
import Pagination from '@/components/market/Pagination.vue'
import SearchResult from '@/components/market/SearchResult.vue'
import TopMenu from '@/components/market/TopMenu.vue'
import NftList from '@/components/market/NftList.vue'
import { getNftList } from '@/api/Mall'
import { AppModule } from '@/store/modules/app'
import BaseFooter from '@/components/layout/BaseFooter.vue'
import NftTypeBar from '@/components/market/NftTypeBar.vue'
import SortSelect from '@/components/market/SortSelect.vue'
import ResultNo from '@/components/market/ResultNo.vue'
import { INftData, parseNftData } from '@/types/Nft'
import TimeLoader from '@/components/main/TimeLoader.vue'
import { preActivateNFT, queryActivateNFTState } from '@/api/Market'
import { createModal, ZModal } from '@/utils/modal.util'
import RewardModal from '@/components/core/RewardModal.vue'
import { ElLoadingComponent } from 'element-ui/types/loading'
import { UserModule } from '@/store/modules/user'
import ChainManager from '@/chain/ChainManager'
import { CONTRACT_ADDRESS } from '@/configs/config_chain'
import { Component, Vue, Watch } from "vue-property-decorator";
import SearchPanel from "@/components/market/SearchPanel.vue";
import Pagination from "@/components/market/Pagination.vue";
import SearchResult from "@/components/market/SearchResult.vue";
import TopMenu from "@/components/market/TopMenu.vue";
import NftList from "@/components/market/NftList.vue";
import { getNftList } from "@/api/Mall";
import { AppModule } from "@/store/modules/app";
import BaseFooter from "@/components/layout/BaseFooter.vue";
import NftTypeBar from "@/components/market/NftTypeBar.vue";
import SortSelect from "@/components/market/SortSelect.vue";
import FilterLeft from "@/components/market/FilterLeft.vue";
import ResultNo from "@/components/market/ResultNo.vue";
import { INftData, parseNftData } from "@/types/Nft";
import TimeLoader from "@/components/main/TimeLoader.vue";
import { preActivateNFT, queryActivateNFTState } from "@/api/Market";
import { createModal, ZModal } from "@/utils/modal.util";
import RewardModal from "@/components/core/RewardModal.vue";
import { ElLoadingComponent } from "element-ui/types/loading";
import { UserModule } from "@/store/modules/user";
import ChainManager from "@/chain/ChainManager";
import { CONTRACT_ADDRESS } from "@/configs/config_chain";
const MYSTERY_BOX_CACHE = 'activate_nft_cache'
const MYSTERY_BOX_CACHE = "activate_nft_cache";
@Component({
components: {
@ -68,285 +95,289 @@ const MYSTERY_BOX_CACHE = 'activate_nft_cache'
NftTypeBar,
BaseFooter,
NftList,
FilterLeft,
SearchResult,
SearchPanel,
Pagination,
TopMenu
}
TopMenu,
},
})
export default class MyNft extends Vue {
mobileFilterShow = false
currentTab = 'mynft'
nftList: INftData[] = []
nftType = 1
nftState = 0
showOrderStatus = false
private filters = ['All Items', 'Normal', 'Selling', 'Renting']
private totalPage = 1
private currentPage = 1
private dataCache: Map<any, INftData[]> = new Map()
mobileFilterShow = false;
currentTab = "mynft";
nftList: INftData[] = [];
nftType = 1;
nftState = 0;
value = 7;
showOrderStatus = false;
private filters = ["All Items", "Normal", "Selling", "Renting"];
private totalPage = 1;
private currentPage = 1;
private dataCache: Map<any, INftData[]> = new Map();
private isProcess = false
private rewardModal: ZModal
orderTimer: any = null
loadingInstance: ElLoadingComponent
chainManager = new ChainManager()
private isProcess = false;
private rewardModal: ZModal;
orderTimer: any = null;
loadingInstance: ElLoadingComponent;
chainManager = new ChainManager();
get accountId() {
return AppModule.accountId
return AppModule.accountId;
}
get isLogin() {
return !!UserModule.token && !!AppModule.step && AppModule.accountId
return !!UserModule.token && !!AppModule.step && AppModule.accountId;
}
get boxProxyAddress() {
return CONTRACT_ADDRESS[AppModule.chainId].nftProxy
return CONTRACT_ADDRESS[AppModule.chainId].nftProxy;
}
searchClear(hero: string) {
console.log(hero, "herio2020");
}
onNftTypeClicked(typeId: number) {
console.log('nft type clicked: ', typeId)
console.log("nft type clicked: ", typeId);
if (this.nftType !== typeId) {
this.nftType = typeId
this.fetchDatas(1)
this.nftType = typeId;
this.fetchDatas(1);
}
}
sliderChange() {}
filterChange(id: number) {
console.log('filter change: ', id)
console.log("filter change: ", id);
if (this.nftState !== id) {
this.nftState = id
this.fetchDatas(1)
this.nftState = id;
this.fetchDatas(1);
}
}
private resetData() {
this.totalPage = 1
this.currentPage = 1
this.nftList.length = 0
this.$forceUpdate()
this.totalPage = 1;
this.currentPage = 1;
this.nftList.length = 0;
this.$forceUpdate();
}
@Watch('isLogin')
@Watch("isLogin")
private accountChange() {
console.log('account change: ', AppModule.accountId)
console.log("account change: ", AppModule.accountId);
if (this.isLogin) {
this.fetchDatas(this.currentPage)
this.checkOrderHistory()
this.fetchDatas(this.currentPage);
this.checkOrderHistory();
} else {
this.resetData()
this.resetData();
}
}
showFilter(val: boolean) {
this.mobileFilterShow = val
this.mobileFilterShow = val;
}
async fetchDatas(pageNo: number) {
if (!AppModule.accountId) {
return
return;
}
const reqData: any = {
account: AppModule.accountId,
page: pageNo,
type: this.nftType
}
type: this.nftType,
};
if (this.nftState > 0) {
reqData.state = this.nftState - 1
reqData.state = this.nftState - 1;
}
if (this.dataCache.has(reqData)) {
this.nftList = this.dataCache.get(reqData)!
this.nftList = this.dataCache.get(reqData)!;
} else {
this.nftList.length = 0
this.nftList.length = 0;
}
const res: any = await getNftList(reqData)
const res: any = await getNftList(reqData);
if (res.nfts) {
this.nftList.length = 0
this.nftList.length = 0;
for (const data of res.nfts) {
const nftData = parseNftData(data)
this.nftList.push(nftData)
const nftData = parseNftData(data);
this.nftList.push(nftData);
}
this.dataCache.set(reqData, this.nftList)
this.dataCache.set(reqData, this.nftList);
}
if (res.page) {
const page = res.page
this.totalPage = page.total_pages || 1
this.currentPage = page.current_page || 1
const page = res.page;
this.totalPage = page.total_pages || 1;
this.currentPage = page.current_page || 1;
}
console.log(res)
console.log(res);
}
toPage(pageNo: number) {
console.log('to page: ', pageNo)
this.fetchDatas(pageNo)
console.log("to page: ", pageNo);
this.fetchDatas(pageNo);
}
showLoading() {
this.loadingInstance = this.$loading({ background: 'rgba(0, 0, 0, 0.8)' })
this.loadingInstance = this.$loading({ background: "rgba(0, 0, 0, 0.8)" });
}
hideLoading() {
this.loadingInstance?.close()
this.loadingInstance?.close();
}
async onActivateClick({ tokenId, type }: {tokenId: string, type: number}) {
console.log('onActivateClick: ', tokenId, type)
async onActivateClick({ tokenId, type }: { tokenId: string; type: number }) {
console.log("onActivateClick: ", tokenId, type);
if (!this.isLogin) {
this.$message({
message: 'You should login first',
type: 'warning',
duration: 5 * 1000
})
return
message: "You should login first",
type: "warning",
duration: 5 * 1000,
});
return;
}
if (this.isProcess) {
this.$message({
message: 'Box open in process',
type: 'warning',
duration: 5 * 1000
})
return
message: "Box open in process",
type: "warning",
duration: 5 * 1000,
});
return;
}
if (!this.boxProxyAddress) {
this.$message({
message: 'You need to connect to supported network',
type: 'warning',
duration: 5 * 1000
})
return
message: "You need to connect to supported network",
type: "warning",
duration: 5 * 1000,
});
return;
}
this.isProcess = true
this.isProcess = true;
const reqData = {
token_id: tokenId
}
this.showLoading()
let nonce, signature, nftNew
token_id: tokenId,
};
this.showLoading();
let nonce, signature, nftNew;
try {
const res: any = await preActivateNFT(reqData)
nonce = res.nonce
signature = res.signature
nftNew = res.new_token_id
const res: any = await preActivateNFT(reqData);
nonce = res.nonce;
signature = res.signature;
nftNew = res.new_token_id;
} catch (err) {
console.log('pre activate err', err)
this.$message.error('activate nft with pre request error')
this.hideLoading()
this.isProcess = false
return false
console.log("pre activate err", err);
this.$message.error("activate nft with pre request error");
this.hideLoading();
this.isProcess = false;
return false;
}
try {
const result = await this.chainManager.activateOneNft(
this.boxProxyAddress, tokenId, nftNew, type, nonce, signature)
console.log('activate nft result: ', result)
const stateData = { token_id: tokenId, txhash: result.transactionHash }
localStorage.setItem(MYSTERY_BOX_CACHE, JSON.stringify(stateData))
this.hideLoading()
this.beginTraceOrderStatus(stateData)
this.boxProxyAddress,
tokenId,
nftNew,
type,
nonce,
signature
);
console.log("activate nft result: ", result);
const stateData = { token_id: tokenId, txhash: result.transactionHash };
localStorage.setItem(MYSTERY_BOX_CACHE, JSON.stringify(stateData));
this.hideLoading();
this.beginTraceOrderStatus(stateData);
} catch (err) {
console.log(err)
this.hideLoading()
this.isProcess = false
this.$message.error('activate nft with error: ' + err)
console.log(err);
this.hideLoading();
this.isProcess = false;
this.$message.error("activate nft with error: " + err);
}
}
checkOrderHistory() {
const historyOrderId = localStorage.getItem(MYSTERY_BOX_CACHE)
const historyOrderId = localStorage.getItem(MYSTERY_BOX_CACHE);
if (historyOrderId && this.accountId) {
try {
const data = JSON.parse(historyOrderId)
this.beginTraceOrderStatus(data)
const data = JSON.parse(historyOrderId);
this.beginTraceOrderStatus(data);
} catch (err) {
localStorage.removeItem(MYSTERY_BOX_CACHE)
localStorage.removeItem(MYSTERY_BOX_CACHE);
}
}
}
beginTraceOrderStatus(cacheData: any) {
this.showOrderStatus = true
this.isProcess = true
this.loadingInstance?.close()
this.showOrderStatus = true;
this.isProcess = true;
this.loadingInstance?.close();
this.orderTimer = setInterval(() => {
this.getOrderStatus(cacheData)
}, 1000)
this.getOrderStatus(cacheData);
}, 1000);
}
async getOrderStatus(data: any) {
console.log('getOrderStatus: ', data)
console.log("getOrderStatus: ", data);
try {
const res: any = await queryActivateNFTState(data)
const res: any = await queryActivateNFTState(data);
if (res.state === 1) {
// success
this.onOpenSuccess(res.nft)
this.onOpenSuccess(res.nft);
}
} catch (err) {
console.log('query order status error', err)
console.log("query order status error", err);
}
}
resetTmpOrderId() {
if (this.orderTimer !== null) {
clearInterval(this.orderTimer)
this.orderTimer = null
clearInterval(this.orderTimer);
this.orderTimer = null;
}
this.isProcess = false
localStorage.removeItem(MYSTERY_BOX_CACHE)
this.loadingInstance?.close()
this.isProcess = false;
localStorage.removeItem(MYSTERY_BOX_CACHE);
this.loadingInstance?.close();
}
async onOpenSuccess(data: any) {
console.log('open success')
console.log("open success");
if (!this.isProcess) {
return
return;
}
this.resetTmpOrderId()
this.showOrderStatus = false
const cardList: INftData[] = []
const nftData = parseNftData(data)
cardList.push(nftData)
this.resetTmpOrderId();
this.showOrderStatus = false;
const cardList: INftData[] = [];
const nftData = parseNftData(data);
cardList.push(nftData);
this.showRewardModal({
title: 'NFT activate Success',
cardList
})
this.fetchDatas(this.currentPage)
title: "NFT activate Success",
cardList,
});
this.fetchDatas(this.currentPage);
// this.$alert('Congratulations', 'Open Success', { type: 'success', confirmButtonText: 'OK' })
}
showRewardModal(data: any) {
console.log('show reward modal with data: ', data)
this.rewardModal = createModal(RewardModal, data)
this.rewardModal.show()
console.log("show reward modal with data: ", data);
this.rewardModal = createModal(RewardModal, data);
this.rewardModal.show();
}
}
</script>
<style lang="scss" scoped>
@import '../../scss/breakpoints.scss';
@import "../../scss/breakpoints.scss";
.mynft {
display: flex;
flex-direction: column;
align-items: center;
// align-items: center;
background-image: url("../../assets/market/bg.png.png");
.container {
display: flex;
flex-direction: column;
width: 1440px;
max-width: 100%;
box-sizing: border-box;
.wrapper{
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: flex-end;
padding: 0 4%;
.left-bar{
width: 40%;
}
}
display: flex;
flex-direction: row;
width: 1440px;
max-width: 100%;
box-sizing: border-box;
.right-part {
width: 100%;
}
}
}
.mobile-top {
display: none;
}
.page-comp{
.page-comp {
width: 100%;
}
.order-status {
@ -363,16 +394,16 @@ export default class MyNft extends Vue {
left: 100px;
top: 100px;
}
@include media('<desktop') {
@include media("<desktop") {
.container {
flex-direction: column;
.wrapper{
.wrapper {
margin-top: 80px;
margin-bottom: -76px;
padding: 0;
.left-bar{
.left-bar {
flex-grow: 1;
width: 50%!important;
width: 50% !important;
padding: 0 15px;
}
}
@ -444,8 +475,8 @@ export default class MyNft extends Vue {
padding: 26px 20px;
}
.show{
display: flex!important;
.show {
display: flex !important;
}
}
</style>