Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Litemall
Commits
9b217226
Commit
9b217226
authored
Apr 15, 2019
by
Junling Bu
Browse files
Merge branch 'litemall-vue' of
https://github.com/pkwenda/litemall
into pkwenda-litemall-vue
parents
3cb559bb
ce4ef458
Changes
156
Expand all
Hide whitespace changes
Inline
Side-by-side
litemall-vue/src/assets/scss/iconfont/iconfont.ttf
0 → 100755
View file @
9b217226
File added
litemall-vue/src/assets/scss/mixin/_one-border.scss
0 → 100755
View file @
9b217226
@mixin
one-border
(
$direction
:
bottom
){
position
:
relative
;
&
::after
{
content
:
""
;
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
200%
;
height
:
200%
;
transform
:
scale
(
.5
);
transform-origin
:
0
0
;
pointer-events
:
none
;
box-sizing
:
border-box
;
border-
#{
$direction
}
:
1px
solid
$
border-color
;
}
}
\ No newline at end of file
litemall-vue/src/assets/scss/spinner.scss
0 → 100644
View file @
9b217226
@keyframes
lds-ball
{
0
%
,
100
%
{
animation-timing-function
:
cubic-bezier
(
0
.45
,
0
,
0
.9
,
0
.55
);
}
0
%
{
-webkit-transform
:
translate
(
0
,
0
);
transform
:
translate
(
0
,
0
);
}
50
%
{
-webkit-transform
:
translate
(
0
,
108px
);
transform
:
translate
(
0
,
108px
);
animation-timing-function
:
cubic-bezier
(
0
,
0
.45
,
0
.55
,
0
.9
);
}
100
%
{
-webkit-transform
:
translate
(
0
,
0
);
transform
:
translate
(
0
,
0
);
}
}
@-webkit-keyframes
lds-ball
{
0
%
,
100
%
{
animation-timing-function
:
cubic-bezier
(
0
.45
,
0
,
0
.9
,
0
.55
);
}
0
%
{
-webkit-transform
:
translate
(
0
,
0
);
transform
:
translate
(
0
,
0
);
}
50
%
{
-webkit-transform
:
translate
(
0
,
108px
);
transform
:
translate
(
0
,
108px
);
animation-timing-function
:
cubic-bezier
(
0
,
0
.45
,
0
.55
,
0
.9
);
}
100
%
{
-webkit-transform
:
translate
(
0
,
0
);
transform
:
translate
(
0
,
0
);
}
}
.lds-ball
{
position
:
relative
;
}
.lds-ball
div
{
width
:
52px
;
height
:
52px
;
border-radius
:
50%
;
background
:
#e15b64
;
-webkit-animation
:
lds-ball
1s
linear
infinite
;
animation
:
lds-ball
1s
linear
infinite
;
}
.lds-ball
{
position
:
fixed
;
left
:
50%
;
top
:
30%
;
transform
:
translateX
(
-50%
);
}
\ No newline at end of file
litemall-vue/src/core/async-loader.js
0 → 100644
View file @
9b217226
// 使用这个会导致组件内部的 router 导航守卫无法使用, 慎用
/**
* @param { string } chunkPath views 文件夹下的页面路径
* @return { function } 返回 promise<component> 的匿名函数
*/
import
spinner
from
'
@/vue/components/spinner
'
;
export
default
chunkPath
=>
{
const
AsyncHandler
=
()
=>
({
component
:
new
Promise
(
resolve
=>
{
setTimeout
(()
=>
{
resolve
(
import
(
/* webpackChunkName: "[request]" */
`@/views/
${
chunkPath
}
`
)
);
},
1000
);
}),
loading
:
spinner
,
error
:
{
render
(
h
)
{
return
h
(
'
div
'
,
{},
[
'
异步组件加载失败
'
]);
}
},
timeout
:
10000
});
return
()
=>
Promise
.
resolve
({
functional
:
true
,
render
(
h
,
{
data
,
children
})
{
return
h
(
AsyncHandler
,
data
,
children
);
}
});
};
litemall-vue/src/core/regexp/index.js
0 → 100755
View file @
9b217226
export
const
idCard
=
/^
[
1-9
]{1}[
0-9
]{14}
$|^
[
1-9
]{1}[
0-9
]{16}([
0-9
]
|
[
xX
])
$/
;
export
const
mobileReg
=
/^1
[
0-9
]{10}
$/
;
export
const
address
=
val
=>
{
const
value
=
val
.
trim
();
return
value
.
length
>=
5
&&
value
.
length
<=
100
;
};
export
const
userName
=
/^
[
a-zA-Z0-9_
\u
4e00-
\u
9fa5
]{3,20}
$/
;
export
const
emailReg
=
/^
(\w)
+
(\.\w
+
)
*@
(\w)
+
((\.\w
+
)
+
)
$/
;
litemall-vue/src/core/utils/auth.js
0 → 100644
View file @
9b217226
import
docCookie
from
'
@/core/utils/cookies
'
import
{
setLocalStorage
,
getLocalStorage
}
from
'
@/core/utils/local-storage
'
;
export
function
procJumpToken
()
{
if
(
docCookie
.
getItem
(
'
litetoken
'
))
{
let
litetoken
=
docCookie
.
getItem
(
'
litetoken
'
)
if
(
!
PSMU
.
isEmtVal
(
litetoken
))
{
let
jsonStr
=
PSMU
.
DU
(
litetoken
)
console
.
log
(
"
jsonStr is :
"
,
jsonStr
);
if
(
!
PSMU
.
isEmt
(
jsonStr
)
&&
PSMU
.
isString
(
jsonStr
))
{
let
tokenInfo
=
JSON
.
parse
(
jsonStr
)
console
.
log
(
"
tokenInfo is :
"
,
tokenInfo
);
if
(
tokenInfo
&&
tokenInfo
.
token
)
{
setLocalStorage
({
Authorization
:
tokenInfo
.
token
});
}
const
infoData
=
getLocalStorage
(
'
Authorization
'
)
console
.
log
(
"
procJumpToken getLocalStorage
"
,
infoData
);
if
(
tokenInfo
&&
tokenInfo
.
userInfo
)
{
// debugger
setLocalStorage
({
avatar
:
tokenInfo
.
userInfo
.
avatarUrl
,
// user_id: data.user_id,
// background_image: data.background_image,
nickName
:
tokenInfo
.
userInfo
.
nickName
});
}
const
infoData2
=
getLocalStorage
(
'
avatarUrl
'
,
'
nickName
'
)
console
.
log
(
"
procJumpToken getLocalStorage 2
"
,
infoData2
);
}
}
docCookie
.
removeItem
(
'
litetoken
'
)
}
}
litemall-vue/src/core/utils/cookies.js
0 → 100644
View file @
9b217226
/*\
|*|
|*| :: cookies.js ::
|*|
|*| A complete cookies reader/writer framework with full unicode support.
|*|
|*| https://developer.mozilla.org/en-US/docs/DOM/document.cookie
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntaxes:
|*|
|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
|*| * docCookies.getItem(name)
|*| * docCookies.removeItem(name[, path], domain)
|*| * docCookies.hasItem(name)
|*| * docCookies.keys()
|*|
\*/
const
docCookies
=
{
getItem
:
function
(
sKey
)
{
return
decodeURIComponent
(
document
.
cookie
.
replace
(
new
RegExp
(
"
(?:(?:^|.*;)
\\
s*
"
+
encodeURIComponent
(
sKey
).
replace
(
/
[\-\.\+\*]
/g
,
"
\\
$&
"
)
+
"
\\
s*
\\
=
\\
s*([^;]*).*$)|^.*$
"
),
"
$1
"
))
||
null
;
},
setItem
:
function
(
sKey
,
sValue
,
vEnd
,
sPath
,
sDomain
,
bSecure
)
{
if
(
!
sKey
||
/^
(?:
expires|max
\-
age|path|domain|secure
)
$/i
.
test
(
sKey
))
{
return
false
;
}
var
sExpires
=
""
;
if
(
vEnd
)
{
switch
(
vEnd
.
constructor
)
{
case
Number
:
sExpires
=
vEnd
===
Infinity
?
"
; expires=Fri, 31 Dec 9999 23:59:59 GMT
"
:
"
; max-age=
"
+
vEnd
;
break
;
case
String
:
sExpires
=
"
; expires=
"
+
vEnd
;
break
;
case
Date
:
sExpires
=
"
; expires=
"
+
vEnd
.
toUTCString
();
break
;
}
}
document
.
cookie
=
encodeURIComponent
(
sKey
)
+
"
=
"
+
encodeURIComponent
(
sValue
)
+
sExpires
+
(
sDomain
?
"
; domain=
"
+
sDomain
:
""
)
+
(
sPath
?
"
; path=
"
+
sPath
:
""
)
+
(
bSecure
?
"
; secure
"
:
""
);
return
true
;
},
removeItem
:
function
(
sKey
,
sPath
,
sDomain
)
{
if
(
!
sKey
||
!
this
.
hasItem
(
sKey
))
{
return
false
;
}
document
.
cookie
=
encodeURIComponent
(
sKey
)
+
"
=; expires=Thu, 01 Jan 1970 00:00:00 GMT
"
+
(
sDomain
?
"
; domain=
"
+
sDomain
:
""
)
+
(
sPath
?
"
; path=
"
+
sPath
:
""
);
return
true
;
},
hasItem
:
function
(
sKey
)
{
return
(
new
RegExp
(
"
(?:^|;
\\
s*)
"
+
encodeURIComponent
(
sKey
).
replace
(
/
[\-\.\+\*]
/g
,
"
\\
$&
"
)
+
"
\\
s*
\\
=
"
)).
test
(
document
.
cookie
);
},
keys
:
/* optional method: you can safely remove it! */
function
()
{
var
aKeys
=
document
.
cookie
.
replace
(
/
((?:
^|
\s
*;
)[^\=]
+
)(?=
;|$
)
|^
\s
*|
\s
*
(?:\=[^
;
]
*
)?(?:\1
|$
)
/g
,
""
).
split
(
/
\s
*
(?:\=[^
;
]
*
)?
;
\s
*/
);
for
(
var
nIdx
=
0
;
nIdx
<
aKeys
.
length
;
nIdx
++
)
{
aKeys
[
nIdx
]
=
decodeURIComponent
(
aKeys
[
nIdx
]);
}
return
aKeys
;
}
};
export
default
docCookies
litemall-vue/src/core/utils/local-storage.js
0 → 100644
View file @
9b217226
export
const
getLocalStorage
=
(...
args
)
=>
{
const
storage
=
{};
args
.
forEach
(
arg
=>
{
storage
[
arg
]
=
window
.
localStorage
.
getItem
(
arg
)
||
null
;
});
return
storage
;
};
export
const
setLocalStorage
=
data
=>
{
Object
.
keys
(
data
).
forEach
(
prop
=>
{
const
el
=
data
[
prop
];
window
.
localStorage
.
setItem
(
prop
,
el
);
});
};
export
const
removeLocalStorage
=
(...
args
)
=>
{
args
.
forEach
(
arg
=>
{
window
.
localStorage
.
removeItem
(
arg
);
});
};
litemall-vue/src/core/utils/location-param.js
0 → 100644
View file @
9b217226
export
default
name
=>
{
const
reg
=
new
RegExp
(
`(^|&)
${
name
}
=([^&]*)(&|$)`
);
const
r
=
window
.
location
.
search
.
substr
(
1
).
match
(
reg
);
if
(
r
!=
null
)
return
decodeURIComponent
(
r
[
2
]);
return
''
;
};
litemall-vue/src/core/utils/psm.js
0 → 100644
View file @
9b217226
const
protobuf
=
require
(
"
protobufjs
"
);
/*尽量保持业务无关 业务相关放chatinfo.js中*/
if
(
!
window
.
PSMU
)
{
var
PSMU
=
{
validChars
:
/^
[\]
,:{}
\s]
*$/
,
validEscape
:
/
\\(?:[
"
\\\/
bfnrt
]
|u
[
0-9a-fA-F
]{4})
/g
,
validTokens
:
/"
[^
"
\\\n\r]
*"|true|false|null|-
?\d
+
(?:\.\d
*
)?(?:[
eE
][
+
\-]?\d
+
)?
/g
,
validBraces
:
/
(?:
^|:|,
)(?:\s
*
\[)
+/g
,
htmlRegArr
:
[],
SERV_LOG_INTERVAL
:
30
*
1000
,
servLogId
:
false
,
servLogMap
:
{},
tokenName
:
'
Authorization
'
,
tuid
:
'
false
'
,
tuidCounter
:
0
,
isUptuid
:
false
,
uptuidDefaultVal
:
9960
,
maxtuidval
:
9999
,
// Base64 encoding table
b64
:
new
Array
(
64
),
// Base64 decoding table
s64
:
new
Array
(
123
),
/*目前全局变量及状态保存到 psm中 组件数据通信频繁的可以放vuex中
* 尽量不依赖vue 增加额外复杂性 */
REV_MSG
:
'
REV_MSG
'
,
/*接收消息*/
REV_ROOM_MSG
:
'
REV_ROOM_MSG
'
,
/*接收房态消息*/
REV_HIS_MSG
:
'
REV_HIS_MSG
'
,
/*接收历史消息*/
LOAD_HIS_MSG_END
:
'
LOAD_HIS_MSG_END
'
,
/*加载历史消息结束*/
SELF_MSG
:
'
SELF_MSG
'
,
/*发出消息*/
RESEND_MSG
:
'
RESEND_MSG
'
,
/*重发消息*/
CHAT_NET_ERR_MSG
:
'
CHAT_NET_ERR_MSG
'
,
/*网络异常消息发送失败*/
OUT_CHAT_PAGE_MSG
:
'
OUT_CHAT_PAGE_MSG
'
,
/*离开聊天页面*/
IN_CHAT_PAGE_MSG
:
'
IN_CHAT_PAGE_MSG
'
,
/*进入聊天页面*/
LOGIN_SUCC
:
'
LOGIN_SUCC
'
,
/*登录成功*/
LOGIN_FAILED
:
'
LOGIN_FAILED
'
,
/*登录失败*/
CODE_ZU
:
'
ZU
'
,
CODE_ZP
:
'
ZP
'
,
codeType
:
false
,
setup
:
function
()
{
PSMU
.
codeType
=
PSMU
.
CODE_ZP
;
// 65..90, 97..122, 48..57, 43, 47
for
(
var
i
=
0
;
i
<
64
;)
PSMU
.
s64
[
PSMU
.
b64
[
i
]
=
i
<
26
?
i
+
65
:
i
<
52
?
i
+
71
:
i
<
62
?
i
-
4
:
i
-
59
|
43
]
=
i
++
;
},
isEmt
:
function
(
value
,
allowBlank
)
{
if
(
PSMU
.
isNotDef
(
value
))
{
return
true
;
}
return
value
===
null
||
value
===
undefined
||
/*((PSMU.isArr(value) && !value.length)) ||*/
(
!
allowBlank
?
value
===
''
:
false
)
||
value
===
"
undefined
"
;
},
isEmtVal
:
function
(
value
)
{
if
(
PSMU
.
isNotDef
(
value
))
{
return
true
;
}
return
value
===
null
||
value
===
'
null
'
||
(
typeof
(
value
)
===
'
string
'
&&
(
value
===
"
undefined
"
||
value
===
''
||
PSMU
.
trim
(
value
)
===
''
))
||
(
typeof
(
value
)
===
'
boolean
'
&&
value
===
false
);
},
isNotDef
:
function
(
value
)
{
return
typeof
(
value
)
===
"
undefined
"
;
},
isArr
:
function
(
obj
)
{
return
Object
.
prototype
.
toString
.
call
(
obj
)
===
'
[object Array]
'
;
},
isString
:
function
(
obj
)
{
return
Object
.
prototype
.
toString
.
call
(
obj
)
===
'
[object String]
'
;
},
isDate
:
function
(
obj
)
{
return
Object
.
prototype
.
toString
.
call
(
obj
)
===
'
[object Date]
'
;
},
isNum
:
function
(
num
)
{
return
(
typeof
(
num
)
===
"
number
"
)
&&
(
num
!==
Infinity
)
&&
!
isNaN
(
num
);
},
isNotEmtArr
:
function
(
o
)
{
return
PSMU
.
isArr
(
o
)
&&
typeof
(
o
.
length
)
&&
o
.
length
>
0
;
},
trim
:
function
(
value
)
{
return
value
.
replace
(
/^
\s
*/
,
""
).
replace
(
/
\s
*$/
,
""
);
},
setBuffer
:
function
(
ret
,
val
)
{
if
(
PSMU
.
isEmt
(
ret
[
ret
.
len
]))
{
ret
[
ret
.
len
]
=
protobuf
.
util
.
newBuffer
(
100
);
}
if
(
ret
.
offset
+
1
>=
ret
.
len
*
100
+
100
)
{
ret
[
++
ret
.
len
]
=
protobuf
.
util
.
newBuffer
(
100
);
}
var
len
=
parseInt
(
ret
.
offset
/
100
);
var
pos
=
ret
.
offset
%
100
;
ret
[
len
][
pos
]
=
val
;
return
++
ret
.
offset
;
},
base64Decode
:
function
(
string
,
/*buffer,*/
offset
)
{
var
ret
=
{
len
:
0
,
offset
:
offset
};
// var start = offset;
var
j
=
0
,
// goto index
t
;
// temporary
for
(
var
i
=
0
;
i
<
string
.
length
;)
{
var
c
=
string
.
charCodeAt
(
i
++
);
if
(
c
===
61
&&
j
>
1
)
break
;
if
((
c
=
PSMU
.
s64
[
c
])
===
undefined
)
throw
Error
(
"
invalid encoding
"
);
switch
(
j
)
{
case
0
:
t
=
c
;
j
=
1
;
break
;
case
1
:
PSMU
.
setBuffer
(
ret
,
t
<<
2
|
(
c
&
48
)
>>
4
);
// buffer[offset++] = t << 2 | (c & 48) >> 4;
t
=
c
;
j
=
2
;
break
;
case
2
:
PSMU
.
setBuffer
(
ret
,
(
t
&
15
)
<<
4
|
(
c
&
60
)
>>
2
);
// buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
t
=
c
;
j
=
3
;
break
;
case
3
:
PSMU
.
setBuffer
(
ret
,
(
t
&
3
)
<<
6
|
c
);
// buffer[offset++] = (t & 3) << 6 | c;
j
=
0
;
break
;
}
}
if
(
j
===
1
)
throw
Error
(
"
invalid encoding
"
);
if
(
ret
.
offset
>
0
)
{
var
buf
=
protobuf
.
util
.
newBuffer
(
ret
.
offset
);
for
(
var
i
=
0
;
i
<
ret
.
offset
;
i
++
)
{
var
len
=
parseInt
(
i
/
100
);
var
pos
=
i
%
100
;
buf
[
i
]
=
ret
[
len
][
pos
];
}
return
buf
;
}
return
null
;
// return offset - start;
},
base64Encode
:
function
(
buffer
,
start
,
end
)
{
var
parts
=
null
,
chunk
=
[];
var
i
=
0
,
// output index
j
=
0
,
// goto index
t
;
// temporary
while
(
start
<
end
)
{
var
b
=
buffer
[
start
++
];
switch
(
j
)
{
case
0
:
chunk
[
i
++
]
=
PSMU
.
b64
[
b
>>
2
];
t
=
(
b
&
3
)
<<
4
;
j
=
1
;
break
;
case
1
:
chunk
[
i
++
]
=
PSMU
.
b64
[
t
|
b
>>
4
];
t
=
(
b
&
15
)
<<
2
;
j
=
2
;
break
;
case
2
:
chunk
[
i
++
]
=
PSMU
.
b64
[
t
|
b
>>
6
];
chunk
[
i
++
]
=
PSMU
.
b64
[
b
&
63
];
j
=
0
;
break
;
}
if
(
i
>
8191
)
{
(
parts
||
(
parts
=
[])).
push
(
String
.
fromCharCode
.
apply
(
String
,
chunk
));
i
=
0
;
}
}
if
(
j
)
{
chunk
[
i
++
]
=
PSMU
.
b64
[
t
];
chunk
[
i
++
]
=
61
;
if
(
j
===
1
)
chunk
[
i
++
]
=
61
;
}
if
(
parts
)
{
if
(
i
)
parts
.
push
(
String
.
fromCharCode
.
apply
(
String
,
chunk
.
slice
(
0
,
i
)));
return
parts
.
join
(
""
);
}
return
String
.
fromCharCode
.
apply
(
String
,
chunk
.
slice
(
0
,
i
));
},
/*TODO*/
DU
:
function
(
str
)
{
if
(
!
PSMU
.
IS_DU
(
str
))
{
return
PSMU
.
DP
(
str
)
}
str
=
str
.
replace
(
/
(
2_3
)(\w{4}
|
\w{2})
/gi
,
function
(
$0
,
$1
,
$2
)
{
return
String
.
fromCharCode
(
parseInt
(
$2
,
16
));
});
return
str
;
},
EU
:
function
(
str
)
{
return
str
.
replace
(
/
([\u
0000-
\u
FFFF
])
/g
,
function
(
$0
)
{
try
{
var
char16tmp
=
parseInt
(
$0
.
charCodeAt
().
toString
(
16
),
16
);
if
(
char16tmp
>=
0x2002
&&
char16tmp
<=
0x200d
)
{
return
""
;
}
}
catch
(
e
)
{
return
""
;
}
if
(
$0
.
charCodeAt
()
<=
16
)
{
return
'
2_3000
'
+
$0
.
charCodeAt
().
toString
(
16
);
}
else
if
(
$0
.
charCodeAt
()
<
256
)
{
return
'
2_300
'
+
$0
.
charCodeAt
().
toString
(
16
);
}
else
{
return
'
2_3
'
+
$0
.
charCodeAt
().
toString
(
16
);
}
});
},
IS_DU
:
function
(
str
)
{
return
str
.
indexOf
(
'
2_3
'
)
==
0
},
EP
:
function
(
json
)
{
if
(
PSMU
.
isEmtVal
(
json
))
{
return
""
;
}
var
root
=
protobuf
.
Root
.
fromJSON
(
protobuf
.
common
.
get
(
'
google/protobuf/struct.proto
'
));
var
StructMessage
=
root
.
lookupType
(
"
google.protobuf.Struct
"
);
var
postDataConverted
=
PSMU
.
json2Struct
(
json
);
var
message
=
StructMessage
.
fromObject
(
postDataConverted
);
var
buf
=
StructMessage
.
encode
(
message
).
finish
();
// this.bufLen=buf.length;
return
PSMU
.
base64Encode
(
buf
,
0
,
buf
.
length
);
},
DP
:
function
(
str
)
{
if
(
PSMU
.
isEmtVal
(
str
))
{
return
""
;
}
if
(
PSMU
.
IS_DU
(
str
))
{
return
PSMU
.
DU
(
str
);
}
// var buf = protobuf.util.newBuffer(protobuf.util.base64.length(str));
// var buf = protobuf.util.newBuffer(this.bufLen);
var
buf
=
PSMU
.
base64Decode
(
str
,
/*buf,*/
0
);
var
root
=
protobuf
.
Root
.
fromJSON
(
protobuf
.
common
.
get
(
'
google/protobuf/struct.proto
'
));
var
StructMessage
=
root
.
lookupType
(
"
google.protobuf.Struct
"
);
var
message2
=
StructMessage
.
decode
(
buf
);
var
struct
=
StructMessage
.
toObject
(
message2
,
protobuf
.
util
.
toJSONOptions
);
return
PSMU
.
struct2Json
(
struct
);
},
struct2Json
:
function
(
structObj
)
{
var
jsonObj
=
{};
var
jsonObjTmp
=
{};
if
(
typeof
structObj
.
fields
===
'
object
'
)
{
jsonObjTmp
=
structObj
.
fields
;
}
Object
.
keys
(
jsonObjTmp
).
forEach
(
function
(
field
)
{
var
fieldObj
=
jsonObjTmp
[
field
];
var
fieldType
=
Object
.
keys
(
fieldObj
)[
0
];
switch
(
fieldType
)
{
case
'
nullValue
'
:
// do nothing
break
;
case
'
numberValue
'
:
case
'
stringValue
'
:
case
'
boolValue
'
:
jsonObj
[
field
]
=
fieldObj
[
fieldType
];
break
;
case
'
structValue
'
:
jsonObj
[
field
]
=
PSMU
.
struct2Json
(
fieldObj
[
fieldType
]);
break
;
case
'
listValue
'
:
jsonObj
[
field
]
=
PSMU
.
list2Json
(
fieldObj
[
fieldType
]);
break
;
}
});
return
jsonObj
;
},
list2Json
:
function
(
listObj
)
{
var
jsonArray
=
[];
var
jsonArrayTmp
=
[];
if
(
PSMU
.
isArr
(
listObj
.
values
))
{
jsonArrayTmp
=
listObj
.
values
;
}
jsonArrayTmp
.
forEach
(
function
(
itemObj
)
{
var
fieldType
=
Object
.
keys
(
itemObj
)[
0
];
switch
(
fieldType
)
{
case
'
nullValue
'
:
// do nothing
break
;
case
'
numberValue
'
:
case
'
stringValue
'
:
case
'
boolValue
'
:
jsonArray
.
push
(
itemObj
[
fieldType
]);
break
;
case
'
structValue
'
:
jsonArray
.
push
(
PSMU
.
struct2Json
(
itemObj
[
fieldType
]));
break
;
case
'
listValue
'
:
jsonArray
.
push
(
PSMU
.
list2Json
(
itemObj
[
fieldType
]));
break
;
}
});
return
jsonArray
;
},
json2Struct
:
function
(
jsonObj
)
{
var
structObj
=
{};
var
structObjTmp
=
{};
if
(
typeof
jsonObj
===
'
object
'
)
{
structObjTmp
=
jsonObj
;
}
Object
.
keys
(
structObjTmp
).
forEach
(
function
(
field
)
{
var
value
=
structObjTmp
[
field
];
switch
(
typeof
(
value
))
{
case
'
number
'
:
structObj
[
field
]
=
{
numberValue
:
value
};
break
;
case
'
string
'
:
structObj
[
field
]
=
{
stringValue
:
value
};
break
;
case
'
boolean
'
:
structObj
[
field
]
=
{
boolValue
:
value
};
break
;
case
'
object
'
:
// null
if
(
!
value
)
break
;
if
(
value
.
constructor
===
Object
)
{
structObj
[
field
]
=
{
structValue
:
PSMU
.
json2Struct
(
value
)
};
}
else
if
(
value
.
constructor
===
Array
)
{
structObj
[
field
]
=
{
listValue
:
PSMU
.
json2List
(
value
)
};
}
break
;
}
});
return
{
fields
:
structObj
};
},
json2List
:
function
(
jsonArray
)
{
var
listObj
=
[];
var
listObjTmp
=
[];
if
(
PSMU
.
isArr
(
jsonArray
))
{
listObjTmp
=
jsonArray
;
}
listObjTmp
.
forEach
(
function
(
jsonObj
)
{
switch
(
typeof
(
jsonObj
))
{
case
'
number
'
:
listObj
.
push
({
numberValue
:
jsonObj
});
break
;
case
'
string
'
:
listObj
.
push
({
stringValue
:
jsonObj
});
break
;
case
'
boolean
'
:
listObj
.
push
({
boolValue
:
jsonObj
});
break
;
case
'
object
'
:
// null
if
(
!
jsonObj
)
break
;
if
(
jsonObj
.
constructor
===
Object
)
{
listObj
.
push
({
structValue
:
PSMU
.
json2Struct
(
jsonObj
)
});
}
else
if
(
jsonObj
.
constructor
===
Array
)
{
listObj
.
push
({
listValue
:
PSMU
.
json2List
(
jsonObj
)
});
}
break
;
}
});
return
{
values
:
listObj
};
},
escapeText
:
function
(
text
)
{
return
(
text
)
?
window
.
escape
(
text
)
:
''
;
},
unescapeText
:
function
(
text
)
{
return
(
text
)
?
window
.
unescape
(
text
)
:
''
;
}
}
window
.
PSMU
=
PSMU
;
}
var
psmu
=
window
.
PSMU
;
export
default
{
psmu
}
litemall-vue/src/core/utils/request.js
0 → 100755
View file @
9b217226
// import axios from 'axios'
// import { Message, MessageBox } from 'element-ui'
// import store from '@/store'
// import { getToken } from '@/utils/auth'
// // create an axios instance
// const service = axios.create({
// baseURL: process.env.BASE_API, // api 的 base_url
// timeout: 5000 // request timeout
// })
// // request interceptor
// service.interceptors.request.use(
// config => {
// // Do something before request is sent
// if (store.getters.token) {
// // 让每个请求携带token-- ['X-Litemall-Admin-Token']为自定义key 请根据实际情况自行修改
// config.headers['X-Litemall-Admin-Token'] = getToken()
// }
// return config
// },
// error => {
// // Do something with request error
// console.log(error) // for debug
// Promise.reject(error)
// }
// )
// // response interceptor
// service.interceptors.response.use(
// response => {
// const res = response.data
// if (res.errno === 501) {
// MessageBox.alert('系统未登录,请重新登录', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// }).then(() => {
// store.dispatch('FedLogOut').then(() => {
// location.reload()
// })
// })
// return Promise.reject('error')
// } else if (res.errno === 502) {
// MessageBox.alert('系统内部错误,请联系管理员维护', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 503) {
// MessageBox.alert('请求业务目前未支持', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 504) {
// MessageBox.alert('更新数据已经失效,请刷新页面重新操作', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 505) {
// MessageBox.alert('更新失败,请再尝试一次', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 506) {
// MessageBox.alert('没有操作权限,请联系管理员授权', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno !== 0) {
// // 非5xx的错误属于业务错误,留给具体页面处理
// return Promise.reject(response)
// } else {
// return response
// }
// }, error => {
// console.log('err' + error)// for debug
// Message({
// message: '登录连接超时(后台不能连接,请联系系统管理员)',
// type: 'error',
// duration: 5 * 1000
// })
// return Promise.reject(error)
// })
// export default service
litemall-vue/src/core/utils/scroll.js
0 → 100755
View file @
9b217226
export
default
{
isAttached
(
element
)
{
let
currentNode
=
element
.
parentNode
;
while
(
currentNode
)
{
if
(
currentNode
.
tagName
===
'
HTML
'
)
{
return
true
;
}
if
(
currentNode
.
nodeType
===
11
)
{
return
false
;
}
currentNode
=
currentNode
.
parentNode
;
}
return
false
;
},
getScrollLeft
(
element
)
{
return
'
scrollLeft
'
in
element
?
element
.
scrollLeft
:
element
.
pageXOffset
;
},
getVisibleHeight
(
element
)
{
return
element
===
window
?
element
.
innerHeight
:
element
.
getBoundingClientRect
().
height
;
},
getVisibleWidth
(
element
)
{
return
element
===
window
?
element
.
innerWidth
:
element
.
getBoundingClientRect
().
width
;
}
};
litemall-vue/src/main.js
0 → 100644
View file @
9b217226
import
Vue
from
'
vue
'
;
import
App
from
'
./App.vue
'
;
import
router
from
'
./vue/router
'
;
import
'
./assets/scss/global.scss
'
;
import
'
@/assets/scss/iconfont/iconfont.css
'
;
import
VeeValidate
,
{
Validator
}
from
'
vee-validate
'
;
import
VueCountdown
from
'
@/vue/plugins/vue-countdown
'
;
import
zhCN
from
'
vee-validate/dist/locale/zh_CN
'
;
import
axios
from
'
@/vue/plugins/axios
'
;
import
filters
from
'
@/vue/filter
'
;
import
psm
from
'
@/core/utils/psm
'
import
{
procJumpToken
}
from
"
@/core/utils/auth
"
;
Vue
.
use
(
VueCountdown
);
Vue
.
use
(
axios
);
Vue
.
use
(
filters
);
Validator
.
localize
(
'
zh-CN
'
,
zhCN
);
Vue
.
use
(
VeeValidate
,
{
locale
:
'
zh-CN
'
});
import
{
Lazyload
,
Icon
,
Cell
,
CellGroup
,
loading
,
Button
,
Toast
}
from
'
vant
'
;
Vue
.
use
(
Icon
);
Vue
.
use
(
Cell
);
Vue
.
use
(
CellGroup
);
Vue
.
use
(
loading
);
Vue
.
use
(
Button
);
Vue
.
use
(
Toast
);
Vue
.
use
(
Lazyload
,
{
preLoad
:
1.3
,
error
:
require
(
'
@/assets/images/goods_default.png
'
),
loading
:
require
(
'
@/assets/images/goods_default.png
'
),
attempt
:
1
,
listenEvents
:
[
'
scroll
'
],
lazyComponent
:
true
});
Vue
.
prototype
.
PSMU
=
psm
.
psmu
PSMU
.
setup
()
procJumpToken
()
Vue
.
config
.
productionTip
=
false
;
new
Vue
({
router
,
render
:
h
=>
h
(
App
)
}).
$mount
(
'
#app
'
);
litemall-vue/src/views/home/tabbar-home-shop-info.vue
0 → 100755
View file @
9b217226
<
template
>
<van-cell-group>
<van-cell>
<van-notice-bar
:text=
"notice"
background=
"white"
:leftIcon=
"trumpet"
style=
"padding-left: 0"
/>
</van-cell>
<van-cell
:title=
"address"
icon=
"dingwei"
isLink
:url=
"mapSrc"
></van-cell>
<van-cell
icon=
"phone"
isLink
>
<template
slot=
"title"
>
<a
:href=
"'tel:' + mobile"
class=
"store_mobile"
>
{{
mobile
}}
</a>
</
template
>
</van-cell>
</van-cell-group>
</template>
<
script
>
import
{
NoticeBar
}
from
'
vant
'
;
import
trumpet
from
'
@/assets/images/trumpet.png
'
;
export
default
{
name
:
'
shop-info-group
'
,
props
:
{
address
:
{
type
:
String
,
required
:
true
},
mobile
:
{
type
:
String
,
required
:
true
},
notice
:
{
type
:
String
,
default
:
''
},
location
:
Object
},
data
()
{
const
{
location
}
=
this
;
const
MAP_PATH
=
`http://m.amap.com/navi/?dest=
${
location
.
lat
}
,
${
location
.
lng
}
&key=ab67b14d58d47912a9feb63ba862450c&destName=
${
location
.
name
}
`
;
return
{
trumpet
,
mapSrc
:
location
?
MAP_PATH
:
'
#
'
};
},
created
()
{},
components
:
{
[
NoticeBar
.
name
]:
NoticeBar
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.store_mobile
{
color
:
#0000a0
;
text-decoration
:
underline
;
}
</
style
>
litemall-vue/src/views/home/tabbar-home-sign-board.vue
0 → 100755
View file @
9b217226
<
template
>
<div
class=
"signboard"
>
<img
:src=
"boardUrl"
:height=
"signboardHeight"
width=
"100%"
>
<div
class=
"store_opacity clearfix"
>
<div
class=
"float-l"
>
{{
storeName
}}
</div>
<div
class=
"float-r store_collect isCollect"
@
click=
"showCollect = true"
>
<van-icon
name=
"shoucang-full"
/>
<span>
收藏
</span>
</div>
</div>
<van-popup
v-model=
"showCollect"
position=
"top"
style=
"background-color: transparent"
>
<img
:src=
"showCollect && collectImg"
@
click=
"showCollect = false"
width=
"100%"
alt=
"右上角收藏"
>
</van-popup>
</div>
</
template
>
<
script
>
import
{
Popup
}
from
'
vant
'
;
import
collectImg
from
'
@/assets/images/index_collect.png
'
;
export
default
{
name
:
'
sign-board
'
,
props
:
{
boardUrl
:
{
type
:
String
,
required
:
true
},
storeName
:
{
type
:
String
,
required
:
true
}
},
data
()
{
const
clientW
=
document
.
body
.
clientWidth
||
document
.
documentElement
.
clientWidth
;
const
signboardHeight
=
clientW
?
(
clientW
*
2
)
/
3
:
250
;
return
{
signboardHeight
,
showCollect
:
false
,
collectImg
};
},
components
:
{
[
Popup
.
name
]:
Popup
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.signboard
{
position
:
relative
;
min-height
:
250px
;
}
.store_opacity
{
position
:
absolute
;
bottom
:
0
;
color
:
#fff
;
width
:
100%
;
background-image
:
linear-gradient
(
rgba
(
0
,
0
,
0
,
0
)
,
rgba
(
0
,
0
,
0
,
1
));
padding
:
15px
10px
;
box-sizing
:
border-box
;
}
.isCollect
i
{
color
:
$red
;
}
</
style
>
litemall-vue/src/views/home/tabbar-home.vue
0 → 100755
View file @
9b217226
<
template
>
<div
class=
"tab_home"
>
<div
class=
"tal_class_searchBox"
>
<van-search
placeholder=
"点击前往搜索"
@
click=
"$router.push(
{ name: 'search' })"/>
<div
class=
"tal_class_searchMask"
></div>
</div>
<van-swipe
:autoplay=
"3000"
indicator-color=
"white"
>
<van-swipe-item
v-for=
"(image, index) in brandList"
:key=
"index"
>
<img
:src=
"image"
style=
"height:230px"
>
</van-swipe-item>
</van-swipe>
<van-tabbar
active-color=
"#7d7e80"
v-model=
"active"
class=
"goods-channel"
>
<van-tabbar-item
@
click=
"changeTabbar(iconJson)"
style=
"font-size:14px"
v-if=
"index
<
5"
v-for=
"(iconJson, index) in shopInfos.channel"
:key=
"index"
:icon=
"iconJson.iconUrl"
>
{{
iconJson
.
name
}}
</van-tabbar-item>
</van-tabbar>
<van-tabbar
active-color=
"#7d7e80"
v-model=
"active"
class=
"goods-channel"
>
<van-tabbar-item
@
click=
"changeTabbar(iconJson)"
style=
"font-size:14px"
v-if=
"index >= 5"
v-for=
"(iconJson, index) in shopInfos.channel"
:key=
"index"
:icon=
"iconJson.iconUrl"
>
{{
iconJson
.
name
}}
</van-tabbar-item>
<van-tabbar-item></van-tabbar-item>
</van-tabbar>
<!--
<van-panel
title=
"优惠券"
style=
" padding-bottom: 10px;"
>
<div
class=
"van-coupon-item"
v-for=
"(coupon,index) in shopInfos.couponList"
:key=
"index"
@
click=
"getCoupon(coupon.id)"
>
<div
class=
"van-coupon-item__content"
>
<div
class=
"van-coupon-item__head"
>
<h2>
<span>
¥
</span>
{{
coupon
.
discount
}}
元
</h2>
<p>
{{
coupon
.
desc
}}
-
{{
coupon
.
tag
}}
</p>
</div>
<div
class=
"van-coupon-item__body"
>
<h2>
{{
coupon
.
name
}}
</h2>
<p>
有效期:
{{
coupon
.
days
}}
天
</p>
</div>
</div>
</div>
</van-panel>
-->
<van-panel
title=
"团购专区"
>
<!--
{{
shopInfos
.
grouponList
}}
-->
<van-card
:thumb-link=
"goDetail(groupGood.goods.id)"
v-for=
"(groupGood ,index) in shopInfos.grouponList"
:key=
"index"
:title=
"groupGood.goods.name"
:desc=
"groupGood.goods.brief"
:num=
"groupGood.groupon_member"
:origin-price=
"groupGood.goods.counterPrice"
:price=
"groupGood.goods.retailPrice +'.00'"
:thumb=
"groupGood.goods.picUrl"
@
native-click=
"goDetail(groupGood.goods.id)"
>
<!--
<div
slot=
"footer"
>
添加日期
{{
item
.
addTime
}}
</div>
-->
</van-card>
</van-panel>
<van-panel
title=
"新品首发"
>
<!--
{{
shopInfos
.
grouponList
}}
-->
<van-row
gutter
>
<van-col
span=
"12"
v-for=
"(newGood ,index) in shopInfos.newGoodsList"
:key=
"index"
>
<router-link
:to=
"
{ path: `/items/detail/${newGood.id}`}">
<img
:src=
"newGood.picUrl"
style=
"width:180px;height:180px;"
>
</router-link>
<span
style=
"padding-left: 20px;position: relative;bottom: 10px; color: rgb(123, 116, 116);white-space: nowrap;"
>
{{
newGood
.
name
}}
</span>
<span
style=
"padding-left: 80px;position: relative;bottom: 10px; color:#ab956d"
>
¥
{{
newGood
.
retailPrice
}}
</span>
</van-col>
</van-row>
</van-panel>
<van-panel
title=
"人气推荐"
>
<!--
{{
shopInfos
.
grouponList
}}
-->
<van-card
:thumb-link=
"goDetail(groupGood.id)"
v-for=
"(groupGood ,index) in shopInfos.hotGoodsList"
:key=
"index"
:title=
"groupGood.name"
:desc=
"groupGood.brief"
:origin-price=
"groupGood.counterPrice"
:price=
"groupGood.retailPrice +'.00'"
:thumb=
"groupGood.picUrl"
@
native-click=
"goDetail(groupGood.id)"
>
<!--
<div
slot=
"footer"
>
添加日期
{{
item
.
addTime
}}
</div>
-->
</van-card>
</van-panel>
<!--
<van-list
v-model=
"loading"
class=
"scroll-load"
:finished=
"finished"
:immediate-check=
"false"
:offset=
"100"
@
load=
"loadMore"
>
<item-group
v-for=
"( group, key ) in itemGroup"
v-if=
"group"
:key=
"key"
class=
"interval_bot"
:setting=
"group.setting"
>
<component
v-for=
"item in group.items"
:goods=
"item"
:key=
"item.id"
:is=
"getStyle(group.setting.style)"
@
click=
"toGoods(item)"
>
<div
slot=
"mask"
v-if=
"lootAll(item)"
>
<img
src=
"../../assets/images/not_enough.png"
alt=
"已抢光"
>
</div>
<div
slot=
"leftTopIcon"
v-if=
"item.as_status
<
2"
>
<img
:src=
"mxStatus(item.as_status)"
alt=
"秒杀"
>
</div>
</component>
</item-group>
</van-list>
-->
</div>
</
template
>
<
script
>
import
{
HOME_module
,
ALL_GOODS
}
from
'
@/api/shop
'
;
import
getLocationParam
from
'
core/utils/location-param
'
;
import
mx_be_to
from
'
@/assets/images/mx_be_to.png
'
;
import
mx_start
from
'
@/assets/images/mx_start.png
'
;
import
SignBoard
from
'
./tabbar-home-sign-board
'
;
import
ShopInfoGroup
from
'
./tabbar-home-shop-info
'
;
import
ItemGroup
from
'
@/vue/components/item-group/
'
;
import
ItemCardVert
from
'
@/vue/components/item-card-vert/
'
;
import
ItemCardHori
from
'
@/vue/components/item-card-hori/
'
;
import
loadMore
from
'
@/vue/mixin/list-load-more
'
;
import
scrollFixed
from
'
@/vue/mixin/scroll-fixed
'
;
import
_
from
'
lodash
'
;
const
coupon
=
{
available
:
1
,
discount
:
0
,
denominations
:
150
,
originCondition
:
0
,
reason
:
''
,
value
:
150
,
name
:
'
优惠券名称
'
,
startAt
:
1489104000
,
endAt
:
1514592000
};
import
{
List
,
Swipe
,
SwipeItem
,
Tabbar
,
TabbarItem
,
Search
,
Panel
,
CouponCell
,
CouponList
,
Toast
,
Card
,
Row
,
Col
}
from
'
vant
'
;
export
default
{
mixins
:
[
loadMore
,
scrollFixed
],
data
()
{
const
shop_id
=
getLocationParam
(
'
shop_id
'
);
return
{
shop_id
,
brandList
:
[],
shopInfos
:
[],
shopInfo
:
null
,
coupons
:
[
coupon
],
itemGroup
:
{
mx_goods
:
null
,
activity_seckill
:
null
,
shop_recommend
:
null
,
goods
:
null
},
mx_be_to
,
mx_start
,
isLoading
:
false
};
},
computed
:
{
location
()
{
const
shopInfo
=
this
.
shopInfo
;
const
local
=
{
name
:
shopInfo
.
shop_name
,
lat
:
shopInfo
.
lat
,
lng
:
shopInfo
.
lng
};
return
local
.
lat
&&
local
.
lng
?
local
:
null
;
}
},
created
()
{
// this.initViews();
this
.
initNewViews
();
},
methods
:
{
goDetail
(
id
)
{
return
`#/items/detail/
${
id
}
`
;
},
async
getCoupon
(
id
)
{
let
errmsg
=
await
this
.
$reqPost
(
'
/wx/coupon/receive
'
,
{
couponId
:
id
});
Toast
.
success
(
'
领取成功
'
);
},
async
changeTabbar
(
o
)
{
let
{
data
}
=
await
this
.
$reqGet
(
`/wx/goods/category?id=
${
o
.
id
}
`
);
let
categoryId
=
data
.
data
.
currentCategory
.
id
;
this
.
$router
.
push
({
path
:
`items/list?keyword=&itemClass=
${
categoryId
}
`
});
},
initViews
()
{
this
.
$reqGet
(
HOME_module
,
{
shop_id
:
this
.
shop_id
,
'
per-page
'
:
this
.
pages
.
perPage
,
page
:
1
}).
then
(
res
=>
{
const
{
shop_info
,
page
}
=
res
.
data
.
data
;
const
{
mx_goods
,
shop_recommend
,
activity_seckill
,
goods
}
=
this
.
decorate
(
res
.
data
.
data
);
this
.
shopInfo
=
shop_info
;
this
.
itemGroup
.
mx_goods
=
mx_goods
;
this
.
itemGroup
.
shop_recommend
=
shop_recommend
;
this
.
itemGroup
.
activity_seckill
=
activity_seckill
;
this
.
itemGroup
.
goods
=
goods
;
this
.
setPages
(
page
);
});
},
initNewViews
()
{
this
.
$reqGet
(
'
/wx/home/index
'
).
then
(
res
=>
{
this
.
shopInfos
=
res
.
data
.
data
;
this
.
brandList
=
[];
_
.
each
(
res
.
data
.
data
.
brandList
,
v
=>
{
this
.
brandList
.
push
(
v
.
picUrl
);
});
});
},
initData
()
{
// return this.$reqGet(ALL_GOODS, {
// shop_id: this.shop_id,
// 'per-page': this.pages.perPage,
// page: this.pages.currPage
// }).then(res => {
// const { items, page } = res.data.data;
// this.itemGroup.goods && this.itemGroup.goods.items.push(...items);
// return page;
// });
},
toGoods
(
item
)
{
// 如果是秒杀商品, 并且已经抢光
if
(
this
.
lootAll
(
item
))
{
this
.
$dialog
.
alert
({
message
:
'
该秒杀商品已抢光,看看别的吧!
'
});
return
;
}
this
.
$router
.
push
({
path
:
`/items/detail/
${
item
.
id
}
`
});
},
groupIcon
(
key
)
{
const
iconGroup
=
{
activity_seckill
:
'
naozhong
'
,
goods
:
'
list
'
,
mx_goods
:
'
n4
'
,
shop_recommend
:
'
good
'
};
return
iconGroup
[
key
]
||
''
;
},
getStyle
(
style
)
{
return
style
?
'
item-card-vert
'
:
'
item-card-hori
'
;
},
decorate
({
mx_goods
,
shop_recommend
,
activity_seckill
,
goods
})
{
if
(
mx_goods
)
{
mx_goods
.
setting
.
icon
=
'
n4
'
;
mx_goods
.
setting
.
title_desc
=
'
分享得金豆
'
;
mx_goods
.
setting
.
title_color
=
'
#db3d3c
'
;
mx_goods
.
setting
.
item_len
=
mx_goods
.
items
.
length
;
}
if
(
shop_recommend
)
{
shop_recommend
.
setting
.
icon
=
'
good
'
;
shop_recommend
.
setting
.
item_len
=
shop_recommend
.
items
.
length
;
}
if
(
activity_seckill
)
{
activity_seckill
.
setting
.
icon
=
'
naozhong
'
;
activity_seckill
.
setting
.
title_color
=
'
#db3d3c
'
;
activity_seckill
.
setting
.
item_len
=
activity_seckill
.
items
.
length
;
}
if
(
goods
)
{
goods
.
setting
.
icon
=
'
list
'
;
goods
.
setting
.
item_len
=
goods
.
items
.
length
;
}
return
{
mx_goods
,
shop_recommend
,
activity_seckill
,
goods
};
},
lootAll
(
item
)
{
return
(
typeof
item
.
as_status
!==
'
undefined
'
&&
item
.
sold_num
==
item
.
total
);
},
mxStatus
(
as_status
)
{
return
as_status
?
this
.
mx_start
:
this
.
mx_be_to
;
}
},
components
:
{
// Vue.use(Tabbar).use(TabbarItem);,
[
Row
.
name
]:
Row
,
[
Col
.
name
]:
Col
,
[
Card
.
name
]:
Card
,
[
Toast
.
name
]:
Toast
,
[
CouponCell
.
name
]:
CouponCell
,
[
CouponList
.
name
]:
CouponList
,
[
Search
.
name
]:
Search
,
[
Panel
.
name
]:
Panel
,
[
List
.
name
]:
List
,
[
Swipe
.
name
]:
Swipe
,
[
SwipeItem
.
name
]:
SwipeItem
,
[
Tabbar
.
name
]:
Tabbar
,
[
TabbarItem
.
name
]:
TabbarItem
,
[
SignBoard
.
name
]:
SignBoard
,
[
ShopInfoGroup
.
name
]:
ShopInfoGroup
,
[
ItemGroup
.
name
]:
ItemGroup
,
[
ItemCardVert
.
name
]:
ItemCardVert
,
[
ItemCardHori
.
name
]:
ItemCardHori
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.interval_bot
{
margin-bottom
:
10px
;
}
.goods-channel
{
position
:
sticky
;
border-bottom-width
:
0px
;
}
.van-coupon-cell--selected
{
color
:
#323233
;
}
.van-coupon-list
{
height
:
100%
;
position
:
relative
;
background-color
:
#f8f8f8
;
}
.van-coupon-list__field
{
padding
:
7px
15px
;
}
.van-coupon-list__exchange
{
height
:
32px
;
line-height
:
30px
;
}
.van-coupon-list__list
{
overflow-y
:
auto
;
padding
:
15px
0
;
-webkit-box-sizing
:
border-box
;
box-sizing
:
border-box
;
-webkit-overflow-scrolling
:
touch
;
}
.van-coupon-list__close
{
left
:
0
;
bottom
:
0
;
position
:
absolute
;
font-weight
:
500
;
}
.van-coupon-list__empty
{
padding-top
:
100px
;
text-align
:
center
;
}
.van-coupon-list__empty
p
{
color
:
#969799
;
margin
:
15px
0
;
font-size
:
14px
;
line-height
:
20px
;
}
.van-coupon-list__empty
img
{
width
:
80px
;
height
:
84px
;
}
.van-coupon-item
{
overflow
:
hidden
;
border-radius
:
4px
;
margin
:
0
15px
15px
;
background-color
:
#fff
;
-webkit-box-shadow
:
0
0
4px
rgba
(
0
,
0
,
0
,
0
.1
);
box-shadow
:
0
0
4px
rgba
(
0
,
0
,
0
,
0
.1
);
}
.van-coupon-item
:active
{
background-color
:
#e8e8e8
;
}
.van-coupon-item__content
{
display
:
-
webkit-box
;
display
:
-
ms-flexbox
;
display
:
flex
;
height
:
100px
;
padding
:
24px
0
0
15px
;
-webkit-box-sizing
:
border-box
;
box-sizing
:
border-box
;
}
.van-coupon-item
h2
,
.van-coupon-item
p
{
margin
:
0
;
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
}
.van-coupon-item
h2
{
height
:
34px
;
font-weight
:
500
;
line-height
:
34px
;
}
.van-coupon-item
p
{
font-size
:
12px
;
line-height
:
16px
;
color
:
#969799
;
}
.van-coupon-item__head
{
min-width
:
90px
;
}
.van-coupon-item__head
h2
{
color
:
#f44
;
font-size
:
24px
;
}
.van-coupon-item__head
h2
span
{
font-size
:
50%
;
}
.van-coupon-item__body
{
-webkit-box-flex
:
1
;
-ms-flex
:
1
;
flex
:
1
;
position
:
relative
;
border-radius
:
0
4px
4px
0
;
}
.van-coupon-item__body
h2
{
font-size
:
16px
;
}
.van-coupon-item__corner
{
top
:
16px
;
right
:
15px
;
position
:
absolute
;
}
.van-coupon-item__corner
.van-icon
{
border-color
:
#f44
;
background-color
:
#f44
;
}
.van-coupon-item__reason
{
padding
:
7px
15px
;
border-top
:
1px
dashed
#ebedf0
;
background-color
:
#fafafa
;
}
.van-coupon-item--disabled
:active
{
background-color
:
#fff
;
}
.van-coupon-item--disabled
.van-coupon-item__content
{
height
:
90px
;
}
.van-coupon-item--disabled
h2
,
.van-coupon-item--disabled
p
,
.van-coupon-item--disabled
span
{
color
:
#969799
;
}
</
style
>
litemall-vue/src/views/items/detail/EntityGroup/area.json
0 → 100755
View file @
9b217226
This diff is collapsed.
Click to expand it.
litemall-vue/src/views/items/detail/EntityGroup/index.vue
0 → 100755
View file @
9b217226
<
template
>
<div
class=
"item_cell_group"
>
<van-cell-group>
<van-cell
title=
"选择规格"
isLink
:value=
"selectSku.selectedSkuComb.sku_str"
@
click.native=
"skuClick"
/>
<van-cell
title=
"商品属性"
isLink
@
click.native=
"propsPopup = true"
/>
<!--
<van-cell
title=
"配送至"
isLink
:value=
"addressVal.area_name"
@
click.native=
"addressPopup = true"
/>
-->
<!--
<van-cell
title=
"运费"
:value=
"postFee | yuan"
/>
-->
</van-cell-group>
<van-sku
v-model=
"showSku"
:showAddCartBtn=
"showAddCartBtn"
:buyText=
"buyText"
:sku=
"skus.sku"
:goods=
"skus.goods_info"
:goodsId=
"goodsInfo.id"
:disableStepperInput=
"true"
@
buy-clicked=
"buyGoods"
@
add-cart=
"onAddCartClicked"
/>
<van-popup
v-model=
"propsPopup"
position=
"bottom"
>
<popup-props
:propsStr=
"props_str"
></popup-props>
</van-popup>
<van-popup
v-model=
"areaPopup"
position=
"bottom"
>
<popup-area
v-if=
"areaPopup"
@
confirm=
"emitAddressVal"
@
cancel=
"areaPopup = false"
/>
</van-popup>
<van-popup
v-model=
"addressPopup"
position=
"bottom"
>
<popup-address
:is-show=
"addressPopup"
:addressVal=
"addressVal"
:default-id=
"defaultId"
@
confirm=
"emitAddressVal"
@
area-click=
"areaClick"
/>
</van-popup>
</div>
</
template
>
<
script
>
const
popupArea
=
()
=>
import
(
/* webpackChunkName: "popup-area" */
'
./popup-area
'
);
import
popupAddress
from
'
./popup-address
'
;
import
popupProps
from
'
./popup-props
'
;
import
actionMixin
from
'
../mix
'
;
import
{
ADDRESS_DEFAULT
}
from
'
@/api/user
'
;
import
_
from
'
lodash
'
;
import
{
debug
}
from
'
util
'
;
// import { POST_FEE } from '@/api/shop';
function
getGoodInfoFromSpecification
(
productLists
,
compareS1
,
compareS2
)
{
if
(
productLists
.
length
===
0
)
{
return
productLists
;
}
_
.
each
(
productLists
,
v
=>
{
if
(
_
.
without
(
v
,
compareS1
,
compareS2
).
length
>
0
)
{
return
v
;
}
});
console
.
error
(
compareS1
+
'
,
'
+
compareS2
+
'
getGoodInfoFromSpecification no match !!!
'
);
return
{};
}
export
default
{
name
:
'
entity-group
'
,
props
:
{
goodsInfo
:
{
type
:
Object
,
default
:
()
=>
({})
},
specification_list
:
{
type
:
Array
,
default
:
()
=>
[]
},
selectSku
:
{
type
:
Object
,
default
:
()
=>
({})
},
addressVal
:
{
type
:
Object
,
default
:
()
=>
({})
}
},
mixins
:
[
actionMixin
],
data
()
{
const
sku
=
this
.
skuAdapter
(
this
.
goodsInfo
.
skus
,
this
.
goodsInfo
.
prop_imgs
);
const
goods_info
=
this
.
setSkuGoodsInfo
(
this
.
goodsInfo
);
const
postFee
=
this
.
goodsInfo
.
is_fenxiao
?
'
免邮费
'
:
''
;
return
{
postFee
,
cartOrBuy
:
''
,
propsPopup
:
false
,
addressPopup
:
false
,
areaPopup
:
false
,
skus
:
{
sku
,
goods_info
},
defaultId
:
-
1
};
},
computed
:
{
props_str
()
{
// this.goodsInfo.props_str = '品牌:GOON大王天使;纸尿裤尺码:S58;';
// if (this.goodsInfo.props_str) {
// return this.goodsInfo.props_str
// .split(';')
// .filter(str => str != '')
// .map(str => str.split(':'));
// }
let
props_arr
=
[];
_
.
each
(
this
.
goodsInfo
.
attribute
,
json
=>
{
props_arr
.
push
([
json
[
'
attribute
'
],
json
[
'
value
'
]]);
});
return
props_arr
||
[];
},
weight
()
{
return
parseFloat
(
this
.
goodsInfo
.
weight
)
*
this
.
selectSku
.
selectedNum
;
}
},
created
()
{
// this.getAddressDefault();
},
methods
:
{
skuClick
(
status
)
{
this
.
cartOrBuy
=
status
;
this
.
showSku
=
true
;
},
buyGoods
(
data
)
{
switch
(
this
.
cartOrBuy
)
{
case
'
cart
'
:
this
.
addCart
(
data
);
break
;
case
'
buy
'
:
this
.
bug
(
data
);
break
;
default
:
break
;
}
// this.$toast(JSON.stringify(data));
this
.
showSku
=
false
;
},
getProductId
(
s1
,
s2
)
{
var
productId
;
let
s1_name
=
_
.
find
(
this
.
specification_list
,
v
=>
{
return
v
.
id
===
s1
;
}).
value
;
let
s2_name
=
_
.
find
(
this
.
specification_list
,
v
=>
{
return
v
.
id
===
s2
;
}).
value
;
_
.
each
(
this
.
goodsInfo
.
productList
,
v
=>
{
let
result
=
_
.
without
(
v
.
specifications
,
s1_name
,
s2_name
);
if
(
result
.
length
===
0
)
{
productId
=
v
.
id
;
}
});
return
productId
;
},
getProductIdByOne
(
s1
)
{
var
productId
;
let
s1_name
=
_
.
find
(
this
.
specification_list
,
v
=>
{
return
v
.
id
===
s1
;
}).
value
;
_
.
each
(
this
.
goodsInfo
.
productList
,
v
=>
{
let
result
=
_
.
without
(
v
.
specifications
,
s1_name
);
if
(
result
.
length
===
0
)
{
productId
=
v
.
id
;
}
});
return
productId
;
},
async
bug
(
data
)
{
console
.
log
(
data
);
// debugger;
let
params
=
{
goodsId
:
data
.
goodsId
,
number
:
data
.
selectedNum
,
productId
:
this
.
getProductIdByOne
(
data
.
selectedSkuComb
.
s1
)
};
// 如果包含s2说明多种规格,目前支持两个规格
if
(
_
.
has
(
data
.
selectedSkuComb
,
'
s2
'
))
{
params
.
productId
=
this
.
getProductId
(
data
.
selectedSkuComb
.
s1
,
data
.
selectedSkuComb
.
s2
);
}
this
.
$reqPost
(
'
/wx/cart/fastadd
'
,
params
).
then
(
req
=>
{
let
cartId
=
req
.
data
.
data
;
// this.$reqGet(
// `/wx/cart/checkout?cartId=${cartId}&addressId=0&couponId=0&grouponRulesId=0`
// ).then(() => {cartId=${cartId}
this
.
$router
.
push
({
name
:
`placeOrderEntity`
,
params
:
{
cartId
:
cartId
}
});
// });
});
},
addCart
(
data
)
{
console
.
log
(
data
);
// debugger;
let
params
=
{
goodsId
:
data
.
goodsId
,
number
:
data
.
selectedNum
,
productId
:
this
.
getProductIdByOne
(
data
.
selectedSkuComb
.
s1
)
};
// 如果包含s2说明多种规格,目前支持两个规格
if
(
_
.
has
(
data
.
selectedSkuComb
,
'
s2
'
))
{
params
.
productId
=
this
.
getProductId
(
data
.
selectedSkuComb
.
s1
,
data
.
selectedSkuComb
.
s2
);
}
this
.
$reqPost
(
'
/wx/cart/add
'
,
params
).
then
(()
=>
{
this
.
$emit
(
'
cart-count
'
,
data
.
selectedNum
);
this
.
$toast
({
message
:
'
已添加至购物车
'
,
duration
:
1500
});
// this.cartInfo = String(parseInt(this.cartInfo) + 1);
});
},
onAddCartClicked
(
data
)
{
this
.
$toast
(
JSON
.
stringify
(
data
));
},
areaClick
()
{
this
.
areaPopup
=
true
;
this
.
addressPopup
=
false
;
},
emitAddressVal
(
data
)
{
this
.
$emit
(
'
update:addressVal
'
,
data
);
},
setSkuGoodsInfo
({
name
,
pic_url
,
sales_price
})
{
return
{
title
:
name
,
picture
:
pic_url
,
price
:
sales_price
};
},
getAddressDefault
()
{
localStorage
.
getItem
(
'
Authorization
'
)
&&
this
.
$reqGet
(
ADDRESS_DEFAULT
).
then
(
res
=>
{
const
data
=
res
.
data
.
data
;
this
.
defaultId
=
data
.
id
;
this
.
emitAddressVal
(
data
);
});
},
skuAdapter
(
skus
=
[],
prop_imgs
=
[])
{
// debugger;
const
tree
=
this
.
setSkuTree
(
skus
,
prop_imgs
);
const
list
=
this
.
setSkuList
(
skus
);
const
skuInfo
=
{
price
:
parseInt
(
this
.
goodsInfo
.
retailPrice
),
// 未选择规格时的价格
stock_num
:
this
.
goodsInfo
.
productList
[
0
].
number
||
1024
,
// 总库存
collection_id
:
''
,
// 无规格商品skuId取collection_id,否则取所选sku组合对应的id
none_sku
:
false
,
// 是否无规格商品
hide_stock
:
false
};
return
{
tree
,
list
,
...
skuInfo
};
},
setSkuList
(
skus
)
{
// debugger;
// return [
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s1: this.goodsInfo.specificationList[0].valueList[0].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s1: this.goodsInfo.specificationList[0].valueList[1].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s2: this.goodsInfo.specificationList[1].valueList[0].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s2: this.goodsInfo.specificationList[1].valueList[1].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// {
// id: 2259, // skuId,下单时后端需要
// price: 30, // 价格(单位分)
// s1: 270, // 规格类目 k_s 为 s1 的对应规格值 id
// s2: 272, // 规格类目 k_s 为 s2 的对应规格值 id
// s3: '0', // 最多包含3个规格值,为0表示不存在该规格
// stock_num: 30 // 当前 sku 组合对应的库存
// }
// ];
var
sku_list
=
[];
// 如果是多种规格则需要特殊处理
if
(
this
.
goodsInfo
.
specificationList
.
length
>
1
)
{
_
.
each
(
this
.
goodsInfo
.
productList
,
v
=>
{
if
(
v
.
specifications
.
length
>
1
)
{
var
sku_list_obj
=
{};
_
.
each
(
v
.
specifications
,
(
specificationName
,
index
)
=>
{
sku_list_obj
[
'
s
'
+
(
~~
index
+
1
)
]
=
this
.
findSpecificationInfoByName
(
specificationName
).
id
;
});
}
sku_list_obj
.
price
=
v
.
price
*
100
;
sku_list_obj
.
stock_num
=
v
.
number
;
sku_list
.
push
(
sku_list_obj
);
});
// debugger;
}
else
{
sku_list
=
[
{
id
:
2259
,
price
:
this
.
goodsInfo
.
retailPrice
*
100
,
discount
:
100
,
code
:
''
,
s1
:
this
.
goodsInfo
.
specificationList
[
0
].
valueList
[
0
].
id
,
// s1: this.goodsInfo.productList[0].id,
kdt_id
:
55
,
discount_price
:
0
,
stock_num
:
this
.
goodsInfo
.
productList
[
0
].
number
||
1024
,
stock_mode
:
0
,
is_sell
:
null
,
combin_sku
:
false
,
goods_id
:
946755
}
];
}
return
sku_list
;
},
findSpecificationInfoByName
(
name
)
{
let
info
=
{};
_
.
each
(
this
.
specification_list
,
specification
=>
{
if
(
specification
.
value
===
name
)
{
info
=
specification
;
}
});
return
info
;
},
setSkuTree
(
skus
,
prop_imgs
)
{
// const skulist = [];
// skus.forEach(el => {
// const propImg = prop_imgs.find(img => img.props == el.props);
// el.props_str_arr = el.props_str.split(';').filter(str => str != '');
// el.props_arr = el.props.split(';').filter(str => str != '');
// el.imgUrl = propImg ? propImg.url : '';
// });
// debugger;
// skus.forEach(el => {
// el.props_str_arr.forEach((sku, i) => {
// const prop = el.props_arr[i];
// // 大规格
// const pName = sku.substr(0, sku.indexOf(':'));
// const k_id = prop.substr(0, prop.indexOf(':'));
// // 规格值 prop_values
// const vName = sku.substr(sku.indexOf(':') + 1);
// const vid = prop.substr(prop.indexOf(':') + 1);
// debugger;
// if (!skulist[i]) {
// skulist[i] = {
// k_id,
// k: pName,
// v: [
// {
// id: vid,
// name: vName,
// imgUrl: el.imgUrl
// }
// ],
// k_s: `s${i + 1}`
// };
// } else {
// const isPass = skulist[i].v.some(val => val.id == vid);
// !isPass &&
// skulist[i].v.push({
// id: vid,
// name: vName,
// imgUrl: el.imgUrl
// });
// }
// });
// });
// return skulist;
let
that
=
this
;
let
specifications
=
[];
_
.
each
(
this
.
goodsInfo
.
specificationList
,
(
v
,
k
)
=>
{
_
.
each
(
v
.
valueList
,
vv
=>
{
vv
.
name
=
vv
.
value
;
_
.
each
(
this
.
goodsInfo
.
productList
,
p
=>
{
if
(
p
.
id
===
vv
.
id
)
{
vv
.
imgUrl
=
p
.
url
;
vv
.
number
=
p
.
number
;
// vv.id = getGoodInfoFromSpecification(
// this.goodsInfo.productList,
// v.name,
// vv.value
// ).id;
//todo id
}
});
_
.
isEmpty
(
vv
.
imgUrl
)
?
(
vv
.
imgUrl
=
this
.
goodsInfo
.
productList
[
0
].
url
)
:
vv
.
imgUrl
;
});
_
.
each
(
v
.
valueList
,
v
=>
{
that
.
specification_list
.
push
(
v
);
});
specifications
.
push
({
k
:
v
.
name
,
v
:
v
.
valueList
,
k_s
:
'
s
'
+
(
~~
k
+
1
)
});
});
// _.each(this.goodsInfo.productList, v => {
// v.imgUrl = v.url;
// v.specification = v.specifications[0];
// });
// specifications.push({
// k: '规格',
// v: this.goodsInfo.productList,
// k_s: 's1'
// });
// debugger;
return
specifications
;
}
},
components
:
{
popupArea
,
[
popupAddress
.
name
]:
popupAddress
,
[
popupProps
.
name
]:
popupProps
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
</
style
>
litemall-vue/src/views/items/detail/EntityGroup/popup-address.vue
0 → 100755
View file @
9b217226
<
template
>
<div
class=
"popup_wrap address_wrap"
>
<van-icon
name=
"clear"
class=
"cancel_popup"
@
click.native=
"hide"
></van-icon>
<!--
<div
class=
"popup_header"
>
配送至
</div>
-->
<div
class=
"popup_content"
>
<van-loading
v-if=
"!addressReady"
class=
"address_popup_load"
type=
"circle"
color=
"black"
/>
<div
v-for=
"(li, i) in address_list"
:key=
"i"
@
click=
"listChoose(li)"
>
<van-tag
plain
type=
"danger"
style=
"margin-right: 5px;"
v-if=
"li.isDefault"
>
默认
</van-tag>
{{
li
.
area_name
+
li
.
address
}}
<van-icon
name=
"success"
class=
"address_active"
v-show=
"addressVal.id == li.id"
></van-icon>
</div>
</div>
<div
class=
"popup_footer"
>
<van-cell-group>
<van-cell
is-link
title=
"其他区域"
@
click.native=
"areaChoose"
></van-cell>
</van-cell-group>
</div>
</div>
</
template
>
<
script
>
import
{
ADDRESS
}
from
'
@/api/user
'
;
import
{
Tag
}
from
'
vant
'
;
export
default
{
name
:
'
popup-address
'
,
props
:
{
isShow
:
Boolean
,
defaultId
:
[
Number
,
String
],
addressVal
:
{
type
:
Object
,
default
:
()
=>
({})
}
},
data
()
{
return
{
addressReady
:
false
,
address_list
:
[],
address_default
:
{}
};
},
watch
:
{
isShow
(
val
)
{
val
&&
!
this
.
address_list
.
length
&&
this
.
getAddress
();
}
},
created
()
{
!
this
.
address_list
.
length
&&
this
.
getAddress
();
},
methods
:
{
hide
()
{
this
.
$parent
.
$emit
(
'
input
'
,
false
);
},
getAddress
()
{
if
(
localStorage
.
getItem
(
'
Authorization
'
))
{
this
.
$reqGet
(
ADDRESS
).
then
(
res
=>
{
const
data
=
res
.
data
.
data
.
map
(
data
=>
{
data
.
isDefault
=
data
.
id
==
this
.
defaultId
;
return
data
;
});
this
.
address_list
=
data
;
this
.
addressReady
=
true
;
});
}
else
{
this
.
address_list
=
[];
this
.
addressReady
=
true
;
}
},
listChoose
(
li
)
{
this
.
$emit
(
'
confirm
'
,
li
);
this
.
hide
();
},
areaChoose
()
{
this
.
$emit
(
'
area-click
'
,
true
);
}
},
components
:
{
[
Tag
.
name
]:
Tag
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
@import
'../../../../assets/scss/var'
;
@import
'../../../../assets/scss/mixin'
;
.popup_wrap
{
position
:
relative
;
padding-bottom
:
30px
;
box-sizing
:
border-box
;
.popup_header
{
padding
:
15px
0
30px
0
;
text-align
:
center
;
}
.popup_content
{
min-height
:
150px
;
max-height
:
400px
;
box-sizing
:
border-box
;
overflow-x
:
hidden
;
overflow-y
:
scroll
;
padding
:
0
10px
;
line-height
:
30px
;
&
::-webkit-scrollbar
{
background-color
:
#fff
;
width
:
5px
;
}
&
::-webkit-scrollbar-thumb
{
border-radius
:
3px
;
background-color
:
#bebebe
;
}
ol
{
padding-left
:
15px
;
list-style
:
decimal
;
}
}
.cancel_popup
{
position
:
absolute
;
right
:
15px
;
top
:
15px
;
z-index
:
9
;
font-size
:
18px
;
}
}
.address_wrap
{
.popup_header
{
@include
one-border
;
text-align
:
left
;
padding-bottom
:
15px
;
padding-left
:
10px
;
margin-bottom
:
15px
;
}
.popup_content
{
@include
one-border
;
line-height
:
22px
;
max-height
:
300px
;
overflow-x
:
hidden
;
overflow-y
:
auto
;
>
div
{
position
:
relative
;
margin-bottom
:
10px
;
padding-right
:
30px
;
}
>
div
.address_popup_load
{
margin
:
0
auto
;
padding
:
0
;
}
>
div
i
{
position
:
absolute
;
right
:
0
;
top
:
50%
;
transform
:
translate
(
0
,
-50%
);
color
:
#fff
;
&
.address_active
{
color
:
$red
;
}
}
}
}
</
style
>
litemall-vue/src/views/items/detail/EntityGroup/popup-area.vue
0 → 100755
View file @
9b217226
<
template
>
<van-area
v-once
:areaList=
"areaList"
@
confirm=
"areaConfirm"
@
cancel=
"areaCanccel"
/>
</
template
>
<
script
>
import
areaList
from
'
./area.json
'
;
import
{
Area
}
from
'
vant
'
;
export
default
{
name
:
'
popup-area
'
,
data
()
{
return
{
areaList
};
},
methods
:
{
areaCanccel
()
{
this
.
$emit
(
'
cancel
'
);
},
areaConfirm
(
areaData
)
{
if
(
areaData
.
every
(
area
=>
area
.
code
!=
-
1
))
{
this
.
$emit
(
'
confirm
'
,
this
.
analyArea
(
areaData
));
this
.
$emit
(
'
cancel
'
);
}
else
{
this
.
$toast
(
'
请选择完整地区
'
);
}
},
analyArea
(
areaData
)
{
const
province
=
areaData
[
0
]
||
{};
const
city
=
areaData
[
1
]
||
{};
const
district
=
areaData
[
2
]
||
{};
return
{
id
:
null
,
area_name
:
`
${
province
.
name
}
${
city
.
name
}
${
district
.
name
}
`
,
district
:
district
.
code
,
city
:
city
.
code
,
province
:
province
.
code
};
}
},
components
:
{
[
Area
.
name
]:
Area
}
};
</
script
>
Prev
1
2
3
4
5
6
7
8
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment