提交
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"i18n-ally.localesPaths": [
|
||||||
|
"common/locales",
|
||||||
|
"uni_modules/uni-table/i18n",
|
||||||
|
"uni_modules/uni-calendar/components/uni-calendar/i18n",
|
||||||
|
"uni_modules/uni-countdown/components/uni-countdown/i18n",
|
||||||
|
"uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n",
|
||||||
|
"uni_modules/uni-fav/components/uni-fav/i18n",
|
||||||
|
"uni_modules/uni-goods-nav/components/uni-goods-nav/i18n",
|
||||||
|
"uni_modules/uni-load-more/components/uni-load-more/i18n",
|
||||||
|
"uni_modules/uni-popup/components/uni-popup/i18n",
|
||||||
|
"uni_modules/uni-pagination/components/uni-pagination/i18n",
|
||||||
|
"uni_modules/uni-search-bar/components/uni-search-bar/i18n",
|
||||||
|
"uni_modules/z-paging/components/z-paging/i18n"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapMutations
|
||||||
|
} from 'vuex'
|
||||||
|
import {
|
||||||
|
version
|
||||||
|
} from './package.json'
|
||||||
|
// #ifdef APP
|
||||||
|
import checkUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
export default {
|
||||||
|
onLaunch: function() {
|
||||||
|
// 线上示例使用
|
||||||
|
// console.log('%c uni-app官方团队诚邀优秀前 端工程师加盟,一起打造更卓越的uni-app & uniCloud,欢迎投递简历到 hr2013@dcloud.io', 'color: red');
|
||||||
|
console.log('App Launch');
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
console.log('App Show')
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
console.log('App Hide')
|
||||||
|
},
|
||||||
|
globalData: {
|
||||||
|
test: ''
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations(['setUniverifyErrorMsg', 'setUniverifyLogin'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import 'uni_modules/uview-ui/index.scss';
|
||||||
|
@import '@/uni_modules/uni-scss/index.scss';
|
||||||
|
/* #ifndef APP-PLUS-NVUE */
|
||||||
|
/* uni.css - 通用组件、模板样式库,可以当作一套ui库应用 */
|
||||||
|
@import './common/uni.css';
|
||||||
|
@import '@/static/customicons.css';
|
||||||
|
/* H5 兼容 pc 所需 */
|
||||||
|
/* #ifdef H5 */
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
body {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 设置所有页面最大宽度为 650px */
|
||||||
|
.uni-app {
|
||||||
|
max-width: 650px;
|
||||||
|
margin: 0 auto;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 确保页面内容也受最大宽度限制 */
|
||||||
|
uni-page-body {
|
||||||
|
max-width: 650px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: #F5F5F5 !important;
|
||||||
|
min-height: 100% !important;
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 顶栏通栏样式 */
|
||||||
|
/* .uni-top-window {
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.uni-top-window uni-tabbar .uni-tabbar {
|
||||||
|
background-color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 隐藏默认 tabBar(使用自定义 tabBar 时) */
|
||||||
|
/* #ifdef H5 */
|
||||||
|
.uni-tabbar,
|
||||||
|
.uni-tabbar__bd,
|
||||||
|
uni-tabbar {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
.uni-app--showleftwindow .hideOnPc {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
/* 以下样式用于 hello uni-app 演示所需 */
|
||||||
|
page {
|
||||||
|
background-color:#F2F2F2;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 28rpx;
|
||||||
|
/* line-height: 1.8; */
|
||||||
|
}
|
||||||
|
.fix-pc-padding {
|
||||||
|
padding: 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-header-logo {
|
||||||
|
padding: 30rpx;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-header-image {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-hello-text {
|
||||||
|
color: #7A7E83;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-hello-addfile {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 300rpx;
|
||||||
|
background: #FFF;
|
||||||
|
padding: 50rpx;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 38rpx;
|
||||||
|
color: #808080;
|
||||||
|
}
|
||||||
|
.movable-area {
|
||||||
|
//可以移动的范围
|
||||||
|
height: 100vh;
|
||||||
|
width: 750rpx;
|
||||||
|
top: 0;
|
||||||
|
position: fixed;
|
||||||
|
pointer-events: none;//此处要加,鼠标事件可以渗透
|
||||||
|
z-index: 11;
|
||||||
|
.movable-view {
|
||||||
|
//按钮大小
|
||||||
|
width:128rpx;
|
||||||
|
height:128rpx;
|
||||||
|
pointer-events: auto;//恢复鼠标事件
|
||||||
|
.index{
|
||||||
|
width: 128rpx;
|
||||||
|
height: 128rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #fff;
|
||||||
|
font-size: 16rpx;
|
||||||
|
line-height: 50rpx;
|
||||||
|
text-align: center;
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* #endif*/
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 DCloud
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// const baseUrl = "https://api.collect.hs.hnzhwlkj.club/"; //这里放置url域名32044
|
||||||
|
// const baseUrl = "https://userdcar-server.hnxinyouhe.com/"; //这里放置url域名32044
|
||||||
|
const baseUrl = "https://usedcar.dev.hnxinyouhe.com/"; //这里放置url域名32044
|
||||||
|
// const baseUrl = "http://219.157.255.213:36010/"; //这里放置url域名32044
|
||||||
|
export function request(options){//封装的requset
|
||||||
|
let { url,data,method,loginType } = options;
|
||||||
|
data = data || {},
|
||||||
|
uni.showLoading({
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取登录类型,优先使用传入的参数,否则从storage读取
|
||||||
|
const loginTypeValue = loginType || uni.getStorageSync('loginType') || 'feishu'
|
||||||
|
|
||||||
|
return new Promise((resolve,rejext)=>{
|
||||||
|
uni.request({//这里是uniapp网络请求的api
|
||||||
|
url: baseUrl + url, //仅为示例,并非真实接口地址。
|
||||||
|
data,
|
||||||
|
header:{
|
||||||
|
'Fdesk-Auth-Token':uni.getStorageSync('token'),
|
||||||
|
'Fdesk-Login-Type': loginTypeValue,
|
||||||
|
'Fdesk-System-Code':'fdesk'
|
||||||
|
},
|
||||||
|
method:method||"GET",//默认请求方式是get
|
||||||
|
success: (res) => {
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
complete: (data)=>{
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function requestx(options){//封装的requset
|
||||||
|
let { url,data,method } = options;
|
||||||
|
data = data || {};
|
||||||
|
return new Promise((resolve,rejext)=>{
|
||||||
|
uni.request({//这里是uniapp网络请求的api
|
||||||
|
url: baseUrl + url, //仅为示例,并非真实接口地址。
|
||||||
|
data,
|
||||||
|
header:{'Authorization': 'Bearer ' + uni.getStorageSync('openid')},
|
||||||
|
method:method||"GET",//默认请求方式是get
|
||||||
|
success: (res) => {
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
complete: (data)=>{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function showToast(options){//封装Toast
|
||||||
|
let { title,duration,icon } = options;
|
||||||
|
uni.showToast({
|
||||||
|
title:title,
|
||||||
|
duration: 2000,
|
||||||
|
icon:icon || "none"
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,262 @@
|
|||||||
|
export default {
|
||||||
|
"list": [{
|
||||||
|
"letter": "A",
|
||||||
|
"data": [
|
||||||
|
"阿克苏机场",
|
||||||
|
"阿拉山口机场",
|
||||||
|
"阿勒泰机场",
|
||||||
|
"阿里昆莎机场",
|
||||||
|
"安庆天柱山机场",
|
||||||
|
"澳门国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "B",
|
||||||
|
"data": [
|
||||||
|
"保山机场",
|
||||||
|
"包头机场",
|
||||||
|
"北海福成机场",
|
||||||
|
"北京南苑机场",
|
||||||
|
"北京首都国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "C",
|
||||||
|
"data": [
|
||||||
|
"长白山机场",
|
||||||
|
"长春龙嘉国际机场",
|
||||||
|
"常德桃花源机场",
|
||||||
|
"昌都邦达机场",
|
||||||
|
"长沙黄花国际机场",
|
||||||
|
"长治王村机场",
|
||||||
|
"常州奔牛机场",
|
||||||
|
"成都双流国际机场",
|
||||||
|
"赤峰机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "D",
|
||||||
|
"data": [
|
||||||
|
"大理机场",
|
||||||
|
"大连周水子国际机场",
|
||||||
|
"大庆萨尔图机场",
|
||||||
|
"大同东王庄机场",
|
||||||
|
"达州河市机场",
|
||||||
|
"丹东浪头机场",
|
||||||
|
"德宏芒市机场",
|
||||||
|
"迪庆香格里拉机场",
|
||||||
|
"东营机场",
|
||||||
|
"敦煌机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "E",
|
||||||
|
"data": [
|
||||||
|
"鄂尔多斯机场",
|
||||||
|
"恩施许家坪机场",
|
||||||
|
"二连浩特赛乌苏国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "F",
|
||||||
|
"data": [
|
||||||
|
"阜阳西关机场",
|
||||||
|
"福州长乐国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "G",
|
||||||
|
"data": [
|
||||||
|
"赣州黄金机场",
|
||||||
|
"格尔木机场",
|
||||||
|
"固原六盘山机场",
|
||||||
|
"广元盘龙机场",
|
||||||
|
"广州白云国际机场",
|
||||||
|
"桂林两江国际机场",
|
||||||
|
"贵阳龙洞堡国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "H",
|
||||||
|
"data": [
|
||||||
|
"哈尔滨太平国际机场",
|
||||||
|
"哈密机场",
|
||||||
|
"海口美兰国际机场",
|
||||||
|
"海拉尔东山国际机场",
|
||||||
|
"邯郸机场",
|
||||||
|
"汉中机场",
|
||||||
|
"杭州萧山国际机场",
|
||||||
|
"合肥骆岗国际机场",
|
||||||
|
"和田机场",
|
||||||
|
"黑河机场",
|
||||||
|
"呼和浩特白塔国际机场",
|
||||||
|
"淮安涟水机场",
|
||||||
|
"黄山屯溪国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "I",
|
||||||
|
"data": []
|
||||||
|
}, {
|
||||||
|
"letter": "J",
|
||||||
|
"data": [
|
||||||
|
"济南遥墙国际机场",
|
||||||
|
"济宁曲阜机场",
|
||||||
|
"鸡西兴凯湖机场",
|
||||||
|
"佳木斯东郊机场",
|
||||||
|
"嘉峪关机场",
|
||||||
|
"锦州小岭子机场",
|
||||||
|
"景德镇机场",
|
||||||
|
"井冈山机场",
|
||||||
|
"九江庐山机场",
|
||||||
|
"九寨黄龙机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "K",
|
||||||
|
"data": [
|
||||||
|
"喀什机场",
|
||||||
|
"克拉玛依机场",
|
||||||
|
"库车龟兹机场",
|
||||||
|
"库尔勒机场",
|
||||||
|
"昆明巫家坝国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "L",
|
||||||
|
"data": [
|
||||||
|
"拉萨贡嘎机场",
|
||||||
|
"兰州中川机场",
|
||||||
|
"丽江三义机场",
|
||||||
|
"黎平机场",
|
||||||
|
"连云港白塔埠机场",
|
||||||
|
"临沧机场",
|
||||||
|
"临沂机场",
|
||||||
|
"林芝米林机场",
|
||||||
|
"柳州白莲机场",
|
||||||
|
"龙岩冠豸山机场",
|
||||||
|
"泸州蓝田机场",
|
||||||
|
"洛阳北郊机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "M",
|
||||||
|
"data": [
|
||||||
|
"满洲里西郊机场",
|
||||||
|
"绵阳南郊机场",
|
||||||
|
"漠河古莲机场",
|
||||||
|
"牡丹江海浪机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "N",
|
||||||
|
"data": [
|
||||||
|
"南昌昌北国际机场",
|
||||||
|
"南充高坪机场",
|
||||||
|
"南京禄口国际机场",
|
||||||
|
"南宁吴圩机场",
|
||||||
|
"南通兴东机场",
|
||||||
|
"南阳姜营机场",
|
||||||
|
"宁波栎社国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "O",
|
||||||
|
"data": []
|
||||||
|
}, {
|
||||||
|
"letter": "P",
|
||||||
|
"data": [
|
||||||
|
"普洱思茅机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "Q",
|
||||||
|
"data": [
|
||||||
|
"齐齐哈尔三家子机场",
|
||||||
|
"秦皇岛山海关机场",
|
||||||
|
"青岛流亭国际机场",
|
||||||
|
"衢州机场",
|
||||||
|
"泉州晋江机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "R",
|
||||||
|
"data": [
|
||||||
|
"日喀则和平机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "S",
|
||||||
|
"data": [
|
||||||
|
"三亚凤凰国际机场",
|
||||||
|
"汕头外砂机场",
|
||||||
|
"上海虹桥国际机场",
|
||||||
|
"上海浦东国际机场",
|
||||||
|
"深圳宝安国际机场",
|
||||||
|
"沈阳桃仙国际机场",
|
||||||
|
"石家庄正定国际机场",
|
||||||
|
"苏南硕放国际机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "T",
|
||||||
|
"data": [
|
||||||
|
"塔城机场",
|
||||||
|
"太原武宿国际机场",
|
||||||
|
"台州路桥机场 (黄岩机场)",
|
||||||
|
"唐山三女河机场",
|
||||||
|
"腾冲驼峰机场",
|
||||||
|
"天津滨海国际机场",
|
||||||
|
"通辽机场",
|
||||||
|
"铜仁凤凰机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "U",
|
||||||
|
"data": []
|
||||||
|
}, {
|
||||||
|
"letter": "V",
|
||||||
|
"data": []
|
||||||
|
}, {
|
||||||
|
"letter": "W",
|
||||||
|
"data": [
|
||||||
|
"万州五桥机场",
|
||||||
|
"潍坊机场",
|
||||||
|
"威海大水泊机场",
|
||||||
|
"文山普者黑机场",
|
||||||
|
"温州永强国际机场",
|
||||||
|
"乌海机场",
|
||||||
|
"武汉天河国际机场",
|
||||||
|
"乌兰浩特机场",
|
||||||
|
"乌鲁木齐地窝堡国际机场",
|
||||||
|
"武夷山机场",
|
||||||
|
"梧州长洲岛机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "X",
|
||||||
|
"data": [
|
||||||
|
"西安咸阳国际机场",
|
||||||
|
"西昌青山机场",
|
||||||
|
"锡林浩特机场",
|
||||||
|
"西宁曹家堡机场",
|
||||||
|
"西双版纳嘎洒机场",
|
||||||
|
"厦门高崎国际机场",
|
||||||
|
"香港国际机场",
|
||||||
|
"襄阳刘集机场",
|
||||||
|
"兴义机场",
|
||||||
|
"徐州观音机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "Y",
|
||||||
|
"data": [
|
||||||
|
"延安二十里堡机场",
|
||||||
|
"盐城机场",
|
||||||
|
"延吉朝阳川机场",
|
||||||
|
"烟台莱山国际机场",
|
||||||
|
"宜宾菜坝机场",
|
||||||
|
"宜昌三峡机场",
|
||||||
|
"伊春林都机场",
|
||||||
|
"伊宁机场",
|
||||||
|
"义乌机场",
|
||||||
|
"银川河东机场",
|
||||||
|
"永州零陵机场",
|
||||||
|
"榆林榆阳机场",
|
||||||
|
"玉树巴塘机场",
|
||||||
|
"运城张孝机场"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
"letter": "Z",
|
||||||
|
"data": [
|
||||||
|
"湛江机场",
|
||||||
|
"昭通机场",
|
||||||
|
"郑州新郑国际机场",
|
||||||
|
"芷江机场",
|
||||||
|
"重庆江北国际机场",
|
||||||
|
"中卫香山机场",
|
||||||
|
"舟山朱家尖机场",
|
||||||
|
"珠海三灶机场"
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
数据验证(表单验证)
|
||||||
|
来自 grace.hcoder.net
|
||||||
|
作者 hcoder 深海
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
error:'',
|
||||||
|
check : function (data, rule){
|
||||||
|
for(var i = 0; i < rule.length; i++){
|
||||||
|
if (!rule[i].checkType){return true;}
|
||||||
|
if (!rule[i].name) {return true;}
|
||||||
|
if (!rule[i].errorMsg) {return true;}
|
||||||
|
if (!data[rule[i].name]) {this.error = rule[i].errorMsg; return false;}
|
||||||
|
switch (rule[i].checkType){
|
||||||
|
case 'string':
|
||||||
|
var reg = new RegExp('^.{' + rule[i].checkRule + '}$');
|
||||||
|
if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
|
||||||
|
break;
|
||||||
|
case 'int':
|
||||||
|
var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$');
|
||||||
|
if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
|
||||||
|
break;
|
||||||
|
break;
|
||||||
|
case 'between':
|
||||||
|
if (!this.isNumber(data[rule[i].name])){
|
||||||
|
this.error = rule[i].errorMsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var minMax = rule[i].checkRule.split(',');
|
||||||
|
minMax[0] = Number(minMax[0]);
|
||||||
|
minMax[1] = Number(minMax[1]);
|
||||||
|
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
|
||||||
|
this.error = rule[i].errorMsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'betweenD':
|
||||||
|
var reg = /^-?[1-9][0-9]?$/;
|
||||||
|
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
|
||||||
|
var minMax = rule[i].checkRule.split(',');
|
||||||
|
minMax[0] = Number(minMax[0]);
|
||||||
|
minMax[1] = Number(minMax[1]);
|
||||||
|
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
|
||||||
|
this.error = rule[i].errorMsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'betweenF':
|
||||||
|
var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
|
||||||
|
if (!reg.test(data[rule[i].name])){this.error = rule[i].errorMsg; return false;}
|
||||||
|
var minMax = rule[i].checkRule.split(',');
|
||||||
|
minMax[0] = Number(minMax[0]);
|
||||||
|
minMax[1] = Number(minMax[1]);
|
||||||
|
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
|
||||||
|
this.error = rule[i].errorMsg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'same':
|
||||||
|
if (data[rule[i].name] != rule[i].checkRule) { this.error = rule[i].errorMsg; return false;}
|
||||||
|
break;
|
||||||
|
case 'notsame':
|
||||||
|
if (data[rule[i].name] == rule[i].checkRule) { this.error = rule[i].errorMsg; return false; }
|
||||||
|
break;
|
||||||
|
case 'email':
|
||||||
|
var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
|
||||||
|
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
|
||||||
|
break;
|
||||||
|
case 'phoneno':
|
||||||
|
var reg = /^1[0-9]{10,10}$/;
|
||||||
|
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
|
||||||
|
break;
|
||||||
|
case 'zipcode':
|
||||||
|
var reg = /^[0-9]{6}$/;
|
||||||
|
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
|
||||||
|
break;
|
||||||
|
case 'reg':
|
||||||
|
var reg = new RegExp(rule[i].checkRule);
|
||||||
|
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
|
||||||
|
break;
|
||||||
|
case 'in':
|
||||||
|
if(rule[i].checkRule.indexOf(data[rule[i].name]) == -1){
|
||||||
|
this.error = rule[i].errorMsg; return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'notnull':
|
||||||
|
if(data[rule[i].name] == null || data[rule[i].name].length < 1){this.error = rule[i].errorMsg; return false;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
isNumber : function (checkVal){
|
||||||
|
var reg = /^-?[1-9][0-9]?.?[0-9]*$/;
|
||||||
|
return reg.test(checkVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,352 @@
|
|||||||
|
/*
|
||||||
|
* HTML5 Parser By Sam Blowes
|
||||||
|
*
|
||||||
|
* Designed for HTML5 documents
|
||||||
|
*
|
||||||
|
* Original code by John Resig (ejohn.org)
|
||||||
|
* http://ejohn.org/blog/pure-javascript-html-parser/
|
||||||
|
* Original code by Erik Arvidsson, Mozilla Public License
|
||||||
|
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* License
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This code is triple licensed using Apache Software License 2.0,
|
||||||
|
* Mozilla Public License or GNU Public License
|
||||||
|
*
|
||||||
|
* ////////////////////////////////////////////////////////////////////////////
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy
|
||||||
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* ////////////////////////////////////////////////////////////////////////////
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS"
|
||||||
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing rights and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Simple HTML Parser.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Erik Arvidsson.
|
||||||
|
* Portions created by Erik Arvidssson are Copyright (C) 2004. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*
|
||||||
|
* ////////////////////////////////////////////////////////////////////////////
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* Usage
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* // Use like so:
|
||||||
|
* HTMLParser(htmlString, {
|
||||||
|
* start: function(tag, attrs, unary) {},
|
||||||
|
* end: function(tag) {},
|
||||||
|
* chars: function(text) {},
|
||||||
|
* comment: function(text) {}
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // or to get an XML string:
|
||||||
|
* HTMLtoXML(htmlString);
|
||||||
|
*
|
||||||
|
* // or to get an XML DOM Document
|
||||||
|
* HTMLtoDOM(htmlString);
|
||||||
|
*
|
||||||
|
* // or to inject into an existing document/DOM node
|
||||||
|
* HTMLtoDOM(htmlString, document);
|
||||||
|
* HTMLtoDOM(htmlString, document.body);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// Regular Expressions for parsing tags and attributes
|
||||||
|
var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
|
||||||
|
var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
|
||||||
|
var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
|
||||||
|
|
||||||
|
var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
|
||||||
|
// fixed by xxx 将 ins 标签从块级名单中移除
|
||||||
|
|
||||||
|
var block = makeMap('a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'); // Inline Elements - HTML 5
|
||||||
|
|
||||||
|
var inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'); // Elements that you can, intentionally, leave open
|
||||||
|
// (and which close themselves)
|
||||||
|
|
||||||
|
var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
|
||||||
|
|
||||||
|
var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
|
||||||
|
|
||||||
|
var special = makeMap('script,style');
|
||||||
|
function HTMLParser(html, handler) {
|
||||||
|
var index;
|
||||||
|
var chars;
|
||||||
|
var match;
|
||||||
|
var stack = [];
|
||||||
|
var last = html;
|
||||||
|
|
||||||
|
stack.last = function () {
|
||||||
|
return this[this.length - 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
while (html) {
|
||||||
|
chars = true; // Make sure we're not in a script or style element
|
||||||
|
|
||||||
|
if (!stack.last() || !special[stack.last()]) {
|
||||||
|
// Comment
|
||||||
|
if (html.indexOf('<!--') == 0) {
|
||||||
|
index = html.indexOf('-->');
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
if (handler.comment) {
|
||||||
|
handler.comment(html.substring(4, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
html = html.substring(index + 3);
|
||||||
|
chars = false;
|
||||||
|
} // end tag
|
||||||
|
|
||||||
|
} else if (html.indexOf('</') == 0) {
|
||||||
|
match = html.match(endTag);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
html = html.substring(match[0].length);
|
||||||
|
match[0].replace(endTag, parseEndTag);
|
||||||
|
chars = false;
|
||||||
|
} // start tag
|
||||||
|
|
||||||
|
} else if (html.indexOf('<') == 0) {
|
||||||
|
match = html.match(startTag);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
html = html.substring(match[0].length);
|
||||||
|
match[0].replace(startTag, parseStartTag);
|
||||||
|
chars = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chars) {
|
||||||
|
index = html.indexOf('<');
|
||||||
|
var text = index < 0 ? html : html.substring(0, index);
|
||||||
|
html = index < 0 ? '' : html.substring(index);
|
||||||
|
|
||||||
|
if (handler.chars) {
|
||||||
|
handler.chars(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function (all, text) {
|
||||||
|
text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
|
||||||
|
|
||||||
|
if (handler.chars) {
|
||||||
|
handler.chars(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
parseEndTag('', stack.last());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (html == last) {
|
||||||
|
throw 'Parse Error: ' + html;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = html;
|
||||||
|
} // Clean up any remaining tags
|
||||||
|
|
||||||
|
|
||||||
|
parseEndTag();
|
||||||
|
|
||||||
|
function parseStartTag(tag, tagName, rest, unary) {
|
||||||
|
tagName = tagName.toLowerCase();
|
||||||
|
|
||||||
|
if (block[tagName]) {
|
||||||
|
while (stack.last() && inline[stack.last()]) {
|
||||||
|
parseEndTag('', stack.last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closeSelf[tagName] && stack.last() == tagName) {
|
||||||
|
parseEndTag('', tagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
unary = empty[tagName] || !!unary;
|
||||||
|
|
||||||
|
if (!unary) {
|
||||||
|
stack.push(tagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler.start) {
|
||||||
|
var attrs = [];
|
||||||
|
rest.replace(attr, function (match, name) {
|
||||||
|
var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[name] ? name : '';
|
||||||
|
attrs.push({
|
||||||
|
name: name,
|
||||||
|
value: value,
|
||||||
|
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (handler.start) {
|
||||||
|
handler.start(tagName, attrs, unary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseEndTag(tag, tagName) {
|
||||||
|
// If no tag name is provided, clean shop
|
||||||
|
if (!tagName) {
|
||||||
|
var pos = 0;
|
||||||
|
} // Find the closest opened tag of the same type
|
||||||
|
else {
|
||||||
|
for (var pos = stack.length - 1; pos >= 0; pos--) {
|
||||||
|
if (stack[pos] == tagName) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos >= 0) {
|
||||||
|
// Close all the open elements, up the stack
|
||||||
|
for (var i = stack.length - 1; i >= pos; i--) {
|
||||||
|
if (handler.end) {
|
||||||
|
handler.end(stack[i]);
|
||||||
|
}
|
||||||
|
} // Remove the open elements from the stack
|
||||||
|
|
||||||
|
|
||||||
|
stack.length = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeMap(str) {
|
||||||
|
var obj = {};
|
||||||
|
var items = str.split(',');
|
||||||
|
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
obj[items[i]] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeDOCTYPE(html) {
|
||||||
|
return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAttrs(attrs) {
|
||||||
|
return attrs.reduce(function (pre, attr) {
|
||||||
|
var value = attr.value;
|
||||||
|
var name = attr.name;
|
||||||
|
|
||||||
|
if (pre[name]) {
|
||||||
|
pre[name] = pre[name] + " " + value;
|
||||||
|
} else {
|
||||||
|
pre[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pre;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseHtml(html) {
|
||||||
|
html = removeDOCTYPE(html);
|
||||||
|
var stacks = [];
|
||||||
|
var results = {
|
||||||
|
node: 'root',
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
HTMLParser(html, {
|
||||||
|
start: function start(tag, attrs, unary) {
|
||||||
|
var node = {
|
||||||
|
name: tag
|
||||||
|
};
|
||||||
|
|
||||||
|
if (attrs.length !== 0) {
|
||||||
|
node.attrs = parseAttrs(attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unary) {
|
||||||
|
var parent = stacks[0] || results;
|
||||||
|
|
||||||
|
if (!parent.children) {
|
||||||
|
parent.children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.children.push(node);
|
||||||
|
} else {
|
||||||
|
stacks.unshift(node);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
end: function end(tag) {
|
||||||
|
var node = stacks.shift();
|
||||||
|
if (node.name !== tag) console.error('invalid state: mismatch end tag');
|
||||||
|
|
||||||
|
if (stacks.length === 0) {
|
||||||
|
results.children.push(node);
|
||||||
|
} else {
|
||||||
|
var parent = stacks[0];
|
||||||
|
|
||||||
|
if (!parent.children) {
|
||||||
|
parent.children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.children.push(node);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
chars: function chars(text) {
|
||||||
|
var node = {
|
||||||
|
type: 'text',
|
||||||
|
text: text
|
||||||
|
};
|
||||||
|
|
||||||
|
if (stacks.length === 0) {
|
||||||
|
results.children.push(node);
|
||||||
|
} else {
|
||||||
|
var parent = stacks[0];
|
||||||
|
|
||||||
|
if (!parent.children) {
|
||||||
|
parent.children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.children.push(node);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
comment: function comment(text) {
|
||||||
|
var node = {
|
||||||
|
node: 'comment',
|
||||||
|
text: text
|
||||||
|
};
|
||||||
|
var parent = stacks[0];
|
||||||
|
|
||||||
|
if (!parent.children) {
|
||||||
|
parent.children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.children.push(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return results.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default parseHtml;
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
export default {
|
||||||
|
// 可以以页面为单位来写,比如首页的内容,写在index字段,个人中心写在center,共同部分写在common部分
|
||||||
|
tabbar: {
|
||||||
|
home: 'home',
|
||||||
|
mine: 'mine'
|
||||||
|
},
|
||||||
|
navbar: {
|
||||||
|
newcar: 'Second hand car entry',
|
||||||
|
changinfo:'Modify information',
|
||||||
|
mycar:'My car source',
|
||||||
|
carinfo:'Vehicle information',
|
||||||
|
drafts :'Drafts',
|
||||||
|
Sold:'Sold',
|
||||||
|
Vehiclesource:'My car source release',
|
||||||
|
},
|
||||||
|
home: {
|
||||||
|
title: 'Henan Heshu Industrial Co., Ltd',
|
||||||
|
langbtn: 'Change Language',
|
||||||
|
addbtn: 'Second hand car entry',
|
||||||
|
loginmsg: "You haven't logged in yet, please log in first and then check again!",
|
||||||
|
loginmsg1: 'One click login means agreement',
|
||||||
|
argin:'I agree and abide by',
|
||||||
|
arginimg:'Please first check and agree to the User Service Agreement and Privacy Policy',
|
||||||
|
Privacy: '《Privacy Policy》',
|
||||||
|
UserAgreement: '《User Service Agreement》',
|
||||||
|
and: 'And',
|
||||||
|
},
|
||||||
|
carinfo: {
|
||||||
|
productName: "Product Name",
|
||||||
|
vin: "VIN",
|
||||||
|
brand: "Brand",
|
||||||
|
product_name: "Product Name",
|
||||||
|
price: "Price(¥)",
|
||||||
|
type: "Type",
|
||||||
|
energy: "Energy",
|
||||||
|
mileage: "Mileage(km)",
|
||||||
|
age: "Age(years)",
|
||||||
|
next: "Next",
|
||||||
|
inputproduct: "Enter product name",
|
||||||
|
inputVIN: "Enter the chassis number/VIN code",
|
||||||
|
inputprice: "import price",
|
||||||
|
inputage: "Enter the age of the vehicle",
|
||||||
|
inputmileage: "Enter mileage",
|
||||||
|
selectbrand: "Select Brand",
|
||||||
|
selecttype: "Select vehicle type",
|
||||||
|
selectmodel: "Select vehicle Model",
|
||||||
|
selectenergy: "Select energy type",
|
||||||
|
model: "Model",
|
||||||
|
"select": "Please select",
|
||||||
|
"front45Degree": "45° Front",
|
||||||
|
"leftFront45Degree": "Left Front 45°",
|
||||||
|
"leftFrontHeadlight": "Left Front Headlight",
|
||||||
|
"front": "Front",
|
||||||
|
"frontLowerPart": "Front Lower Part",
|
||||||
|
"wheelHub": "Wheel Hub",
|
||||||
|
"rightFrontSeat": "Right Front Seat",
|
||||||
|
"rightBottomEdge": "Right Bottom Edge",
|
||||||
|
"rightRearTaillight": "Right Rear Taillight",
|
||||||
|
"rightRear45Degree": "Right Rear 45°",
|
||||||
|
"rearLowerPart": "Rear Lower Part",
|
||||||
|
"trunk": "Trunk",
|
||||||
|
"leftBottomEdge": "Left Bottom Edge",
|
||||||
|
"rearSeat": "Rear Seat",
|
||||||
|
"console": "Console",
|
||||||
|
"controlPanel": "Control Panel",
|
||||||
|
"gearLever": "Gear Lever",
|
||||||
|
"key": "Key",
|
||||||
|
"steeringWheel": "Steering Wheel",
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"displayedMileage": "Displayed Mileage",
|
||||||
|
"leftFrontDoorPanel": "Left Front Door Panel",
|
||||||
|
"leftFrontDoorFunctionArea": "Left Front Door Function Area",
|
||||||
|
"leftFrontSeat": "Left Front Seat",
|
||||||
|
"ceiling": "Ceiling",
|
||||||
|
mag:'Vehicle condition description',
|
||||||
|
maginput:'Enter vehicle description...',
|
||||||
|
errormag:'Reason for failure',
|
||||||
|
errormaginput:'Reason for failure...',
|
||||||
|
"store_status": "Inventory Status",
|
||||||
|
"in_stock": "In Stock",
|
||||||
|
"in_transit": "In Transit",
|
||||||
|
"on_order": "On Order",
|
||||||
|
"location": "Location",
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
next: 'Next',
|
||||||
|
previous:'Back',
|
||||||
|
submit:'Submit',
|
||||||
|
save: "Save",
|
||||||
|
exit:'Exit',
|
||||||
|
edit:'Go modify it'
|
||||||
|
},
|
||||||
|
mine: {
|
||||||
|
title: 'Account',
|
||||||
|
Vehiclesource:'My car source release',
|
||||||
|
drafts:'Drafts',
|
||||||
|
Sold:'Sold',
|
||||||
|
avatar: "Avatar",
|
||||||
|
nickname: "Nickname",
|
||||||
|
phone: "Phone Number",
|
||||||
|
company: "Company",
|
||||||
|
nickinput:'Please fill in the nickname',
|
||||||
|
phoneinput:'Please provide your phone number',
|
||||||
|
companyinput:'Please fill in the company',
|
||||||
|
},
|
||||||
|
zh: 'Chinese',
|
||||||
|
en: 'English',
|
||||||
|
ru: 'Russian',
|
||||||
|
cancel: 'cancel',
|
||||||
|
confirm: 'confirm',
|
||||||
|
prompt: 'prompt',
|
||||||
|
login: 'One click login',
|
||||||
|
empty:'No vehicle source data available at the moment!',
|
||||||
|
emptycg:'Draft box currently has no data!',
|
||||||
|
emptysold:'No data has been sold yet!',
|
||||||
|
status0:'in review',
|
||||||
|
status1:'Under release',
|
||||||
|
status2:'Review failed',
|
||||||
|
view:'View',
|
||||||
|
message:'The product name cannot be empty!',
|
||||||
|
messagesucc:'Login succeeded!',
|
||||||
|
keyword:"Please enter search keywords",
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
export default {
|
||||||
|
// 可以以页面为单位来写,比如首页的内容,写在index字段,个人中心写在center,共同部分写在common部分
|
||||||
|
"tabbar": {
|
||||||
|
"home": "Главная",
|
||||||
|
"mine": "Мой"
|
||||||
|
},
|
||||||
|
"navbar": {
|
||||||
|
"newcar": "Ввоз подержанных автомобилей",
|
||||||
|
"changinfo": "Изменить информацию",
|
||||||
|
"mycar": "Мои автомобили",
|
||||||
|
"carinfo": "Информация об автомобиле",
|
||||||
|
"drafts": "Черновики",
|
||||||
|
"Sold": "Проданные",
|
||||||
|
"Vehiclesource": "Мои объявления"
|
||||||
|
},
|
||||||
|
"home": {
|
||||||
|
"title": "Henan HESU Industrial Co., Ltd",
|
||||||
|
"langbtn": "Сменить язык",
|
||||||
|
"addbtn": "Ввоз подержанных автомобилей",
|
||||||
|
"loginmsg": "Вы не вошли в систему. Пожалуйста, войдите, чтобы продолжить!",
|
||||||
|
"loginmsg1": "Вход означает согласие с",
|
||||||
|
"argin":'Согласен и соблюдаю.',
|
||||||
|
"arginimg":'Пожалуйста, соглашайтесь с Пользовательским соглашением и Политикой конфиденциальности.',
|
||||||
|
"Privacy": "«Политикой конфиденциальности»",
|
||||||
|
"UserAgreement": "«Пользовательским соглашением»",
|
||||||
|
"and": "и"
|
||||||
|
},
|
||||||
|
"carinfo": {
|
||||||
|
"productName": "Название продукта",
|
||||||
|
"vin": "VIN-код",
|
||||||
|
"brand": "Марка",
|
||||||
|
"product_name": "Название продукта",
|
||||||
|
"price": "Цена (¥)",
|
||||||
|
"type": "Тип",
|
||||||
|
"energy": "Тип топлива",
|
||||||
|
"mileage": "Пробег (км)",
|
||||||
|
"age": "Возраст (лет)",
|
||||||
|
"next": "Далее",
|
||||||
|
"selectmodel": "Выбор типа транспортного средства",
|
||||||
|
"model": "моделями",
|
||||||
|
"inputproduct": "Введите название продукта",
|
||||||
|
"inputVIN": "Введите номер рамы / VIN - код",
|
||||||
|
"inputprice": "Введите цену",
|
||||||
|
"inputage": "Введите возраст автомобиля",
|
||||||
|
"inputmileage": "Введите пробег",
|
||||||
|
"selectbrand": "Выберите марку",
|
||||||
|
"selecttype": "Выберите тип автомобиля",
|
||||||
|
"selectenergy": "Выберите тип топлива",
|
||||||
|
"select": "Пожалуйста, выберите",
|
||||||
|
"front45Degree": "45° спереди",
|
||||||
|
"leftFront45Degree": "45° слева спереди",
|
||||||
|
"leftFrontHeadlight": "Левая фара",
|
||||||
|
"front": "Вид спереди",
|
||||||
|
"frontLowerPart": "Нижняя часть передка",
|
||||||
|
"wheelHub": "Колёсные диски",
|
||||||
|
"rightFrontSeat": "Переднее правое сиденье",
|
||||||
|
"rightBottomEdge": "Правая нижняя кромка",
|
||||||
|
"rightRearTaillight": "Правый задний фонарь",
|
||||||
|
"rightRear45Degree": "45° справа сзади",
|
||||||
|
"rearLowerPart": "Нижняя часть задка",
|
||||||
|
"trunk": "Багажник",
|
||||||
|
"leftBottomEdge": "Левая нижняя кромка",
|
||||||
|
"rearSeat": "Задние сиденья",
|
||||||
|
"console": "Центральная консоль",
|
||||||
|
"controlPanel": "Панель управления",
|
||||||
|
"gearLever": "Рычаг КПП",
|
||||||
|
"key": "Ключ",
|
||||||
|
"steeringWheel": "Руль",
|
||||||
|
"dashboard": "Приборная панель",
|
||||||
|
"displayedMileage": "Пробег на одометре",
|
||||||
|
"leftFrontDoorPanel": "Панель левой передней двери",
|
||||||
|
"leftFrontDoorFunctionArea": "Функциональная зона левой передней двери",
|
||||||
|
"leftFrontSeat": "Левое переднее сиденье",
|
||||||
|
"ceiling": "Потолок салона",
|
||||||
|
"mag": "Описание состояния",
|
||||||
|
"maginput": "Введите описание автомобиля...",
|
||||||
|
"errormag": "Причина отказа",
|
||||||
|
"errormaginput": "Причина отказа...",
|
||||||
|
"store_status": "Статус склада",
|
||||||
|
"in_stock": "В наличии",
|
||||||
|
"in_transit": "В пути",
|
||||||
|
"on_order": "На заказ",
|
||||||
|
"location": "Местоположение",
|
||||||
|
},
|
||||||
|
"button": {
|
||||||
|
"next": "Далее",
|
||||||
|
"previous": "Назад",
|
||||||
|
"submit": "Отправить",
|
||||||
|
"save": "Сохранить",
|
||||||
|
"exit": "Выход",
|
||||||
|
"edit": "Изменить"
|
||||||
|
},
|
||||||
|
"mine": {
|
||||||
|
"title": "Мой",
|
||||||
|
"Vehiclesource": "Мои объявления",
|
||||||
|
"drafts": "Черновики",
|
||||||
|
"Sold": "Проданные",
|
||||||
|
"avatar": "Аватар",
|
||||||
|
"nickname": "Никнейм",
|
||||||
|
"phone": "Телефон",
|
||||||
|
"company": "Компания",
|
||||||
|
"nickinput": "Введите никнейм",
|
||||||
|
"phoneinput": "Введите телефон",
|
||||||
|
"companyinput": "Введите название компании"
|
||||||
|
},
|
||||||
|
"zh": "Китайский",
|
||||||
|
"en": "Английский",
|
||||||
|
"ru": "Русский",
|
||||||
|
"cancel": "Отмена",
|
||||||
|
"confirm": "Подтвердить",
|
||||||
|
"prompt": "Подсказка",
|
||||||
|
"login": "Быстрый вход",
|
||||||
|
"empty": "Нет данных об автомобилях!",
|
||||||
|
"emptycg": "Нет черновиков!",
|
||||||
|
"emptysold": "Нет проданных автомобилей!",
|
||||||
|
"status0": "На проверке",
|
||||||
|
"status1": "Опубликовано",
|
||||||
|
"status2": "Не прошло проверку",
|
||||||
|
"view": "Просмотр",
|
||||||
|
"message":'Название продукта не может быть пустым!',
|
||||||
|
"messagesucc":'Регистрация завершена!',
|
||||||
|
"keyword": "Ключевые слова поиска",
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
export default {
|
||||||
|
// 可以以页面为单位来写,比如首页的内容,写在index字段,个人中心写在center,共同部分写在common部分
|
||||||
|
tabbar: {
|
||||||
|
home: '首页',
|
||||||
|
mine: '我的'
|
||||||
|
},
|
||||||
|
navbar: {
|
||||||
|
newcar: '二手车录入',
|
||||||
|
changinfo:'修改信息',
|
||||||
|
mycar:'我的车源',
|
||||||
|
carinfo:'车辆信息',
|
||||||
|
drafts :'草稿箱',
|
||||||
|
Sold:'已出售',
|
||||||
|
Vehiclesource:'我的车源发布',
|
||||||
|
},
|
||||||
|
home: {
|
||||||
|
title: '河南合塑实业有限公司',
|
||||||
|
langbtn: '切换语言',
|
||||||
|
addbtn: '二手车录入',
|
||||||
|
loginmsg: '您还未登录,请先登录后再进行查看!',
|
||||||
|
loginmsg1: '一键登录即代表同意',
|
||||||
|
argin:'我同意并遵守',
|
||||||
|
arginimg:'请先勾选同意用户服务协议以及隐私政策',
|
||||||
|
Privacy: '《隐私政策》',
|
||||||
|
UserAgreement: '《用户服务协议》',
|
||||||
|
and: '和',
|
||||||
|
|
||||||
|
},
|
||||||
|
carinfo: {
|
||||||
|
productName: "产品名称",
|
||||||
|
vin: "车辆识别码",
|
||||||
|
brand: "品牌",
|
||||||
|
model: "型号",
|
||||||
|
product_image: "产品图",
|
||||||
|
price: "售价(¥)",
|
||||||
|
type: "类型",
|
||||||
|
energy: "能源",
|
||||||
|
mileage: "里程(公里数)",
|
||||||
|
age: "车龄(年)",
|
||||||
|
next: "下一步",
|
||||||
|
inputproduct: "输入产品名称",
|
||||||
|
inputVIN: "输入车架号/VIN码",
|
||||||
|
inputprice: "输入价格",
|
||||||
|
inputage: "输入车辆年限",
|
||||||
|
inputmileage: "输入里程",
|
||||||
|
selectbrand: "选择品牌",
|
||||||
|
selecttype: "选择车辆类型",
|
||||||
|
selectmodel: "选择车辆型号",
|
||||||
|
selectenergy: "选择能源类型",
|
||||||
|
select: "请选择",
|
||||||
|
"front45Degree": "45°正脸",
|
||||||
|
"leftFront45Degree": "左前45°",
|
||||||
|
"leftFrontHeadlight": "左前大灯",
|
||||||
|
"front": "正前",
|
||||||
|
"frontLowerPart": "车头下部",
|
||||||
|
"wheelHub": "车辆轮毂",
|
||||||
|
"rightFrontSeat": "右侧前排座椅",
|
||||||
|
"rightBottomEdge": "右侧底大边",
|
||||||
|
"rightRearTaillight": "右后尾灯",
|
||||||
|
"rightRear45Degree": "右后45°",
|
||||||
|
"rearLowerPart": "车尾下部",
|
||||||
|
"trunk": "后备厢",
|
||||||
|
"leftBottomEdge": "左侧底大边",
|
||||||
|
"rearSeat": "后排座椅",
|
||||||
|
"console": "中控台",
|
||||||
|
"controlPanel": "中控面板",
|
||||||
|
"gearLever": "档把",
|
||||||
|
"key": "钥匙",
|
||||||
|
"steeringWheel": "方向盘",
|
||||||
|
"dashboard": "仪表盘",
|
||||||
|
"displayedMileage": "表显里程",
|
||||||
|
"leftFrontDoorPanel": "左前门内饰板",
|
||||||
|
"leftFrontDoorFunctionArea": "左前门功能区",
|
||||||
|
"leftFrontSeat": "左侧前排座椅",
|
||||||
|
"ceiling": "车内顶棚",
|
||||||
|
mag:'车况描述',
|
||||||
|
maginput:'输入车辆描述...',
|
||||||
|
errormag:'未通过原因',
|
||||||
|
errormaginput:'未通过原因...',
|
||||||
|
"store_status": "库存状态",
|
||||||
|
"in_stock": "现货",
|
||||||
|
"in_transit": "在途",
|
||||||
|
"on_order": "订购",
|
||||||
|
"location": "位置",
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
next: '下一步',
|
||||||
|
previous:'上一步',
|
||||||
|
submit:'提交',
|
||||||
|
save: "保存",
|
||||||
|
exit:'退出',
|
||||||
|
edit:'去修改'
|
||||||
|
},
|
||||||
|
mine: {
|
||||||
|
title: '我的',
|
||||||
|
Vehiclesource:'我的车源发布',
|
||||||
|
drafts:'草稿箱',
|
||||||
|
Sold:'已出售',
|
||||||
|
avatar: "头像",
|
||||||
|
nickname: "昵称",
|
||||||
|
phone: "手机号",
|
||||||
|
company: "公司",
|
||||||
|
nickinput:'请填写昵称',
|
||||||
|
phoneinput:'请填写手机号',
|
||||||
|
companyinput:'请填写公司',
|
||||||
|
|
||||||
|
},
|
||||||
|
zh: '中文',
|
||||||
|
en: '英语',
|
||||||
|
ru: '俄语',
|
||||||
|
cancel: '取消',
|
||||||
|
confirm: '确定',
|
||||||
|
prompt: '提示',
|
||||||
|
login: '一键登录',
|
||||||
|
empty:'暂无车源数据!',
|
||||||
|
emptycg:'草稿箱暂无数据!',
|
||||||
|
emptysold:'暂无已出售数据!',
|
||||||
|
status0:'审核中',
|
||||||
|
status1:'发布中',
|
||||||
|
status2:'审核未通过',
|
||||||
|
view:'查看',
|
||||||
|
message:'产品名称不能为空!',
|
||||||
|
messagesucc:'登录成功!',
|
||||||
|
keyword:"请输入搜索关键词",
|
||||||
|
}
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
/// null = 未请求,1 = 已允许,0 = 拒绝|受限, 2 = 系统未开启
|
||||||
|
|
||||||
|
var isIOS
|
||||||
|
|
||||||
|
function album() {
|
||||||
|
var result = 0;
|
||||||
|
var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
|
||||||
|
var authStatus = PHPhotoLibrary.authorizationStatus();
|
||||||
|
if (authStatus === 0) {
|
||||||
|
result = null;
|
||||||
|
} else if (authStatus == 3) {
|
||||||
|
result = 1;
|
||||||
|
} else {
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(PHPhotoLibrary);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function camera() {
|
||||||
|
var result = 0;
|
||||||
|
var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
|
||||||
|
var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
|
||||||
|
if (authStatus === 0) {
|
||||||
|
result = null;
|
||||||
|
} else if (authStatus == 3) {
|
||||||
|
result = 1;
|
||||||
|
} else {
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(AVCaptureDevice);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function location() {
|
||||||
|
var result = 0;
|
||||||
|
var cllocationManger = plus.ios.import("CLLocationManager");
|
||||||
|
var enable = cllocationManger.locationServicesEnabled();
|
||||||
|
var status = cllocationManger.authorizationStatus();
|
||||||
|
if (!enable) {
|
||||||
|
result = 2;
|
||||||
|
} else if (status === 0) {
|
||||||
|
result = null;
|
||||||
|
} else if (status === 3 || status === 4) {
|
||||||
|
result = 1;
|
||||||
|
} else {
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(cllocationManger);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function push() {
|
||||||
|
var result = 0;
|
||||||
|
var UIApplication = plus.ios.import("UIApplication");
|
||||||
|
var app = UIApplication.sharedApplication();
|
||||||
|
var enabledTypes = 0;
|
||||||
|
if (app.currentUserNotificationSettings) {
|
||||||
|
var settings = app.currentUserNotificationSettings();
|
||||||
|
enabledTypes = settings.plusGetAttribute("types");
|
||||||
|
if (enabledTypes == 0) {
|
||||||
|
result = 0;
|
||||||
|
console.log("推送权限没有开启");
|
||||||
|
} else {
|
||||||
|
result = 1;
|
||||||
|
console.log("已经开启推送功能!")
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(settings);
|
||||||
|
} else {
|
||||||
|
enabledTypes = app.enabledRemoteNotificationTypes();
|
||||||
|
if (enabledTypes == 0) {
|
||||||
|
result = 3;
|
||||||
|
console.log("推送权限没有开启!");
|
||||||
|
} else {
|
||||||
|
result = 4;
|
||||||
|
console.log("已经开启推送功能!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(app);
|
||||||
|
plus.ios.deleteObject(UIApplication);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function contact() {
|
||||||
|
var result = 0;
|
||||||
|
var CNContactStore = plus.ios.import("CNContactStore");
|
||||||
|
var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
|
||||||
|
if (cnAuthStatus === 0) {
|
||||||
|
result = null;
|
||||||
|
} else if (cnAuthStatus == 3) {
|
||||||
|
result = 1;
|
||||||
|
} else {
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(CNContactStore);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function record() {
|
||||||
|
var result = null;
|
||||||
|
var avaudiosession = plus.ios.import("AVAudioSession");
|
||||||
|
var avaudio = avaudiosession.sharedInstance();
|
||||||
|
var status = avaudio.recordPermission();
|
||||||
|
console.log("permissionStatus:" + status);
|
||||||
|
if (status === 1970168948) {
|
||||||
|
result = null;
|
||||||
|
} else if (status === 1735552628) {
|
||||||
|
result = 1;
|
||||||
|
} else {
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(avaudiosession);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calendar() {
|
||||||
|
var result = null;
|
||||||
|
var EKEventStore = plus.ios.import("EKEventStore");
|
||||||
|
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
|
||||||
|
if (ekAuthStatus == 3) {
|
||||||
|
result = 1;
|
||||||
|
console.log("日历权限已经开启");
|
||||||
|
} else {
|
||||||
|
console.log("日历权限没有开启");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(EKEventStore);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function memo() {
|
||||||
|
var result = null;
|
||||||
|
var EKEventStore = plus.ios.import("EKEventStore");
|
||||||
|
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
|
||||||
|
if (ekAuthStatus == 3) {
|
||||||
|
result = 1;
|
||||||
|
console.log("备忘录权限已经开启");
|
||||||
|
} else {
|
||||||
|
console.log("备忘录权限没有开启");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(EKEventStore);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function requestIOS(permissionID) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
switch (permissionID) {
|
||||||
|
case "push":
|
||||||
|
resolve(push());
|
||||||
|
break;
|
||||||
|
case "location":
|
||||||
|
resolve(location());
|
||||||
|
break;
|
||||||
|
case "record":
|
||||||
|
resolve(record());
|
||||||
|
break;
|
||||||
|
case "camera":
|
||||||
|
resolve(camera());
|
||||||
|
break;
|
||||||
|
case "album":
|
||||||
|
resolve(album());
|
||||||
|
break;
|
||||||
|
case "contact":
|
||||||
|
resolve(contact());
|
||||||
|
break;
|
||||||
|
case "calendar":
|
||||||
|
resolve(calendar());
|
||||||
|
break;
|
||||||
|
case "memo":
|
||||||
|
resolve(memo());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resolve(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestAndroid(permissionID) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
plus.android.requestPermissions(
|
||||||
|
[permissionID],
|
||||||
|
function(resultObj) {
|
||||||
|
var result = 0;
|
||||||
|
for (var i = 0; i < resultObj.granted.length; i++) {
|
||||||
|
var grantedPermission = resultObj.granted[i];
|
||||||
|
console.log('已获取的权限:' + grantedPermission);
|
||||||
|
result = 1
|
||||||
|
}
|
||||||
|
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
|
||||||
|
var deniedPresentPermission = resultObj.deniedPresent[i];
|
||||||
|
console.log('拒绝本次申请的权限:' + deniedPresentPermission);
|
||||||
|
result = 0
|
||||||
|
}
|
||||||
|
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
|
||||||
|
var deniedAlwaysPermission = resultObj.deniedAlways[i];
|
||||||
|
console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
|
||||||
|
result = -1
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
console.log('result error: ' + error.message)
|
||||||
|
resolve({
|
||||||
|
code: error.code,
|
||||||
|
message: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotoAppPermissionSetting() {
|
||||||
|
if (permission.isIOS) {
|
||||||
|
var UIApplication = plus.ios.import("UIApplication");
|
||||||
|
var application2 = UIApplication.sharedApplication();
|
||||||
|
var NSURL2 = plus.ios.import("NSURL");
|
||||||
|
var setting2 = NSURL2.URLWithString("app-settings:");
|
||||||
|
application2.openURL(setting2);
|
||||||
|
plus.ios.deleteObject(setting2);
|
||||||
|
plus.ios.deleteObject(NSURL2);
|
||||||
|
plus.ios.deleteObject(application2);
|
||||||
|
} else {
|
||||||
|
var Intent = plus.android.importClass("android.content.Intent");
|
||||||
|
var Settings = plus.android.importClass("android.provider.Settings");
|
||||||
|
var Uri = plus.android.importClass("android.net.Uri");
|
||||||
|
var mainActivity = plus.android.runtimeMainActivity();
|
||||||
|
var intent = new Intent();
|
||||||
|
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
|
||||||
|
intent.setData(uri);
|
||||||
|
mainActivity.startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const permission = {
|
||||||
|
get isIOS(){
|
||||||
|
return typeof isIOS === 'boolean' ? isIOS : (isIOS = uni.getSystemInfoSync().platform === 'ios')
|
||||||
|
},
|
||||||
|
requestIOS: requestIOS,
|
||||||
|
requestAndroid: requestAndroid,
|
||||||
|
gotoAppSetting: gotoAppPermissionSetting
|
||||||
|
}
|
||||||
|
|
||||||
|
export default permission
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* 角色管理工具
|
||||||
|
* 统一H5端和PC端的角色控制逻辑
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 角色常量
|
||||||
|
export const ROLE_TYPES = {
|
||||||
|
SUPPLIER: 'supplier', // 供应商
|
||||||
|
BUSINESS: 'business', // 买家
|
||||||
|
PROCUREMENT: 'procurement' // 卖家
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成角色数组(与PC端保持一致)
|
||||||
|
* @param {number} role - 基础角色 (0=供应商, 1=买家, 2=卖家)
|
||||||
|
* @param {number} role_wp - 附加角色 (1/2/3=供应商身份)
|
||||||
|
* @returns {string[]} 角色数组
|
||||||
|
*/
|
||||||
|
export function getRoles(role, role_wp) {
|
||||||
|
const roleMap = {
|
||||||
|
0: ROLE_TYPES.SUPPLIER,
|
||||||
|
1: ROLE_TYPES.BUSINESS,
|
||||||
|
2: ROLE_TYPES.PROCUREMENT
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseRole = roleMap[role] || ROLE_TYPES.BUSINESS
|
||||||
|
const roles = [baseRole]
|
||||||
|
|
||||||
|
// role_wp 有值表示供应商身份
|
||||||
|
if (role_wp && role_wp > 0) {
|
||||||
|
roles.push(ROLE_TYPES.SUPPLIER)
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户角色列表
|
||||||
|
* @returns {string[]} 角色数组
|
||||||
|
*/
|
||||||
|
export function getUserRoles() {
|
||||||
|
try {
|
||||||
|
const rolesStr = uni.getStorageSync('roles')
|
||||||
|
if (rolesStr) {
|
||||||
|
return JSON.parse(rolesStr)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[getUserRoles] 解析角色失败:', e)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主角色(基础角色)
|
||||||
|
* @returns {string} 主角色名称
|
||||||
|
*/
|
||||||
|
export function getPrimaryRole() {
|
||||||
|
const roles = getUserRoles()
|
||||||
|
return roles.length > 0 ? roles[0] : ROLE_TYPES.BUSINESS
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否有供应商身份
|
||||||
|
* @returns {boolean} 是否有供应商身份
|
||||||
|
*/
|
||||||
|
export function isSupplier() {
|
||||||
|
const roles = getUserRoles()
|
||||||
|
return roles.includes(ROLE_TYPES.SUPPLIER)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存角色信息
|
||||||
|
* @param {number} role - 基础角色
|
||||||
|
* @param {number} role_wp - 附加角色
|
||||||
|
* @returns {string[]} 保存后的角色数组
|
||||||
|
*/
|
||||||
|
export function saveRoles(role, role_wp) {
|
||||||
|
const roles = getRoles(role, role_wp)
|
||||||
|
uni.setStorageSync('role', String(role))
|
||||||
|
uni.setStorageSync('roles', JSON.stringify(roles))
|
||||||
|
return roles
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* TabBar 配置管理
|
||||||
|
* 根据用户角色动态显示不同的 tabbar
|
||||||
|
*
|
||||||
|
* 角色定义:
|
||||||
|
* - role=0: 供应商
|
||||||
|
* - role=1: 买家
|
||||||
|
* - role=2: 卖家
|
||||||
|
* - role_wp(有值): 供应商附加身份
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getUserRoles, ROLE_TYPES, isSupplier, getPrimaryRole } from './role.js'
|
||||||
|
|
||||||
|
// 所有可用的 tabbar 配置
|
||||||
|
export const tabBarConfig = [
|
||||||
|
{
|
||||||
|
pagePath: 'pages/index/index',
|
||||||
|
iconPath: '/static/image/home1.png',
|
||||||
|
selectedIconPath: '/static/image/home.png',
|
||||||
|
text: '首页',
|
||||||
|
// 首页:买家或卖家可见(供应商单独时不可见)
|
||||||
|
roles: [ROLE_TYPES.BUSINESS, ROLE_TYPES.PROCUREMENT]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: 'pages/index/publish',
|
||||||
|
iconPath: '/static/image/publish1.png',
|
||||||
|
selectedIconPath: '/static/image/publish.png',
|
||||||
|
text: '发布',
|
||||||
|
// 发布:卖家可见
|
||||||
|
roles: [ROLE_TYPES.PROCUREMENT]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: 'pages/index/publishPro',
|
||||||
|
iconPath: '/static/image/publish1.png',
|
||||||
|
selectedIconPath: '/static/image/publish.png',
|
||||||
|
text: '发布',
|
||||||
|
// 专业发布:有供应商身份可见
|
||||||
|
isSupplier: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: 'pages/index/mine',
|
||||||
|
iconPath: '/static/image/mine1.png',
|
||||||
|
selectedIconPath: '/static/image/mine.png',
|
||||||
|
text: '我的',
|
||||||
|
roles: [] // 所有人可见
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可见的 tabbar 列表
|
||||||
|
* @returns {Array} 过滤后的 tabbar 列表
|
||||||
|
*/
|
||||||
|
export function getVisibleTabBar() {
|
||||||
|
const userRoles = getUserRoles()
|
||||||
|
return tabBarConfig.filter(item => {
|
||||||
|
// 检查 roles 条件
|
||||||
|
if (item.roles && item.roles.length > 0) {
|
||||||
|
if (!item.roles.some(r => userRoles.includes(r))) return false
|
||||||
|
}
|
||||||
|
// 检查 isSupplier 条件
|
||||||
|
if (item.isSupplier && !isSupplier()) return false
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户角色(主角色)
|
||||||
|
* @returns {string} 主角色名称
|
||||||
|
*/
|
||||||
|
export function getUserRole() {
|
||||||
|
return getPrimaryRole()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前 tabbar 的索引
|
||||||
|
* @param {string} currentPath - 当前页面路径
|
||||||
|
* @returns {number} tabbar 索引,-1 表示不在 tabbar 中
|
||||||
|
*/
|
||||||
|
export function getCurrentTabIndex(currentPath) {
|
||||||
|
const visibleTabs = getVisibleTabBar()
|
||||||
|
|
||||||
|
// 移除路径前缀的 / 进行匹配
|
||||||
|
const path = currentPath.startsWith('/') ? currentPath.slice(1) : currentPath
|
||||||
|
|
||||||
|
const index = visibleTabs.findIndex(item => {
|
||||||
|
const itemPath = item.pagePath.startsWith('/') ? item.pagePath.slice(1) : item.pagePath
|
||||||
|
return itemPath === path
|
||||||
|
})
|
||||||
|
|
||||||
|
return index
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* TabBar Mixin
|
||||||
|
* 用于在页面中自动显示/隐藏自定义 tabbar
|
||||||
|
*/
|
||||||
|
import { getVisibleTabBar, getCurrentTabIndex } from '@/common/tabbar.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showTabBar: false,
|
||||||
|
tabBarCurrent: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.checkShowTabBar()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
this.checkShowTabBar()
|
||||||
|
this.updateTabBarCurrent()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
checkShowTabBar() {
|
||||||
|
// 获取当前页面路径
|
||||||
|
const pages = getCurrentPages()
|
||||||
|
const currentPage = pages[pages.length - 1]
|
||||||
|
const currentPath = currentPage.route || currentPage.$route?.path || ''
|
||||||
|
|
||||||
|
// 获取可见的 tabbar 列表
|
||||||
|
const visibleTabs = getVisibleTabBar()
|
||||||
|
|
||||||
|
// 检查当前页面是否在 tabbar 列表中
|
||||||
|
const path = currentPath.startsWith('/') ? currentPath.slice(1) : currentPath
|
||||||
|
const isTabBarPage = visibleTabs.some(item => {
|
||||||
|
const itemPath = item.pagePath.startsWith('/') ? item.pagePath.slice(1) : item.pagePath
|
||||||
|
return itemPath === path
|
||||||
|
})
|
||||||
|
|
||||||
|
this.showTabBar = isTabBarPage
|
||||||
|
},
|
||||||
|
updateTabBarCurrent() {
|
||||||
|
if (this.showTabBar) {
|
||||||
|
const pages = getCurrentPages()
|
||||||
|
const currentPage = pages[pages.length - 1]
|
||||||
|
const currentPath = currentPage.route || currentPage.$route?.path || ''
|
||||||
|
this.tabBarCurrent = getCurrentTabIndex(currentPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/* #ifndef APP-PLUS-NVUE */
|
||||||
|
page {
|
||||||
|
min-height: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
/* 解决头条小程序字体图标不显示问题,因为头条运行时自动插入了span标签,且有全局字体 */
|
||||||
|
/* #ifdef MP-TOUTIAO */
|
||||||
|
/* text :not(view) {
|
||||||
|
font-family: uniicons;
|
||||||
|
} */
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
.uni-icon {
|
||||||
|
font-family: uniicons;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-container {
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-header-logo {
|
||||||
|
/* #ifdef H5 */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
padding: 15px 15px;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-header-image {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-hello-text {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hello-text {
|
||||||
|
color: #7A7E83;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hello-link {
|
||||||
|
color: #7A7E83;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-panel {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-panel-h {
|
||||||
|
/* #ifdef H5 */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
background-color: #ffffff;
|
||||||
|
flex-direction: row !important;
|
||||||
|
/* justify-content: space-between !important; */
|
||||||
|
align-items: center !important;
|
||||||
|
padding: 12px;
|
||||||
|
/* #ifdef H5 */
|
||||||
|
cursor: pointer;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
.uni-panel-h:active {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
.uni-panel-h-on {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-panel-text {
|
||||||
|
flex: 1;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-panel-icon {
|
||||||
|
margin-left: 15px;
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
transition-duration: 0s;
|
||||||
|
transition-property: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-panel-icon-on {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navigate-item {
|
||||||
|
/* #ifdef H5 */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-color: #f0f0f0;
|
||||||
|
border-top-width: 1px;
|
||||||
|
padding: 12px;
|
||||||
|
/* #ifdef H5 */
|
||||||
|
cursor: pointer;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navigate-item:active {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navigate-text {
|
||||||
|
flex: 1;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navigate-icon {
|
||||||
|
margin-left: 15px;
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
function formatTime(time) {
|
||||||
|
if (typeof time !== 'number' || time < 0) {
|
||||||
|
return time
|
||||||
|
}
|
||||||
|
|
||||||
|
var hour = parseInt(time / 3600)
|
||||||
|
time = time % 3600
|
||||||
|
var minute = parseInt(time / 60)
|
||||||
|
time = time % 60
|
||||||
|
var second = time
|
||||||
|
|
||||||
|
return ([hour, minute, second]).map(function(n) {
|
||||||
|
n = n.toString()
|
||||||
|
return n[1] ? n : '0' + n
|
||||||
|
}).join(':')
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatLocation(longitude, latitude) {
|
||||||
|
if (typeof longitude === 'string' && typeof latitude === 'string') {
|
||||||
|
longitude = parseFloat(longitude)
|
||||||
|
latitude = parseFloat(latitude)
|
||||||
|
}
|
||||||
|
|
||||||
|
longitude = longitude.toFixed(2)
|
||||||
|
latitude = latitude.toFixed(2)
|
||||||
|
|
||||||
|
return {
|
||||||
|
longitude: longitude.toString().split('.'),
|
||||||
|
latitude: latitude.toString().split('.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var dateUtils = {
|
||||||
|
UNITS: {
|
||||||
|
'年': 31557600000,
|
||||||
|
'月': 2629800000,
|
||||||
|
'天': 86400000,
|
||||||
|
'小时': 3600000,
|
||||||
|
'分钟': 60000,
|
||||||
|
'秒': 1000
|
||||||
|
},
|
||||||
|
humanize: function(milliseconds) {
|
||||||
|
var humanize = '';
|
||||||
|
for (var key in this.UNITS) {
|
||||||
|
if (milliseconds >= this.UNITS[key]) {
|
||||||
|
humanize = Math.floor(milliseconds / this.UNITS[key]) + key + '前';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return humanize || '刚刚';
|
||||||
|
},
|
||||||
|
format: function(dateStr) {
|
||||||
|
var date = this.parse(dateStr)
|
||||||
|
var diff = Date.now() - date.getTime();
|
||||||
|
if (diff < this.UNITS['天']) {
|
||||||
|
return this.humanize(diff);
|
||||||
|
}
|
||||||
|
var _format = function(number) {
|
||||||
|
return (number < 10 ? ('0' + number) : number);
|
||||||
|
};
|
||||||
|
return date.getFullYear() + '/' + _format(date.getMonth() + 1) + '/' + _format(date.getDate()) + '-' +
|
||||||
|
_format(date.getHours()) + ':' + _format(date.getMinutes());
|
||||||
|
},
|
||||||
|
parse: function(str) { //将"yyyy-mm-dd HH:MM:ss"格式的字符串,转化为一个Date对象
|
||||||
|
var a = str.split(/[^0-9]/);
|
||||||
|
return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
formatTime,
|
||||||
|
formatLocation,
|
||||||
|
dateUtils
|
||||||
|
}
|
||||||
@@ -0,0 +1,406 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<view class="car-cards" >
|
||||||
|
<view class="heard">
|
||||||
|
<view class="" @click="handleCardTap">
|
||||||
|
编号:{{item.code?item.code:'~'}}
|
||||||
|
</view>
|
||||||
|
<view v-if="ismy">
|
||||||
|
<u-icon @click="detilsfn(item)" name="edit-pen-fill" size="25" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="car-card" @click="handleCardTap">
|
||||||
|
<image class="thumb" :src="item.images_pull[0]" mode="aspectFill" />
|
||||||
|
<view class="info">
|
||||||
|
<view class="row row1">
|
||||||
|
<text class="name u-line-1">{{ item.product_name }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="row row2">
|
||||||
|
<view class="kv">
|
||||||
|
<text class="k">车源地</text>
|
||||||
|
<text class="v u-line-1">{{ item.source_place }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="kv">
|
||||||
|
<text class="k">车身颜色</text>
|
||||||
|
<text class="v u-line-1">{{ item.body_color }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="row row3">
|
||||||
|
<view class="kv">
|
||||||
|
<text class="k">上牌时间</text>
|
||||||
|
<text class="v">{{ formatPlateTime(item.plate_time) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="kv">
|
||||||
|
<text class="k">里程</text>
|
||||||
|
<text class="v">{{ item.mileage }} <text v-if="item.mileage">Km</text> </text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 操作区:保存 + 分享(方案A:卡片右下角悬浮) -->
|
||||||
|
<view class="card-actions">
|
||||||
|
<view class="actions-lift" @click="handleCardTap">
|
||||||
|
<text class="">创建时间:</text>
|
||||||
|
<text class="">{{ item.created_at }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="right-btn">
|
||||||
|
<view class="action-btn" @tap.stop="handleToggleSave">
|
||||||
|
<u-icon name="download" size="18" />
|
||||||
|
</view>
|
||||||
|
<view class="action-btn" @tap.stop="handleShare">
|
||||||
|
<u-icon name="share" size="18" />
|
||||||
|
</view>
|
||||||
|
<view class="action-btn" @tap.stop="handleSet(item)" v-if="item.status==1">
|
||||||
|
<u-icon name="setting" size="18" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CarCard',
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
ismy:{
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
default: -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
detilsfn(item){
|
||||||
|
const id = item.id
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/index/publishedit?id=${id}`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
formatPlateTime(dateStr) {
|
||||||
|
return String(dateStr || '').slice(0, 7) // "2026-01"
|
||||||
|
},
|
||||||
|
pdfchanges() {
|
||||||
|
this.$emit('pdfchange')
|
||||||
|
},
|
||||||
|
handleSet(item){
|
||||||
|
const that = this
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确认标记已售出?',
|
||||||
|
success: res => {
|
||||||
|
if (res.confirm) {
|
||||||
|
request({
|
||||||
|
url:'common/usedcar/update/status',
|
||||||
|
method:'post',
|
||||||
|
data: {id:item.id,status:2}
|
||||||
|
}).then(res => {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
that.$emit('restchange')
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
})
|
||||||
|
} else if (res.cancel) {
|
||||||
|
console.log('用户点击取消');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleCardTap() {
|
||||||
|
// 直接处理跳转,避免事件传递问题
|
||||||
|
if (this.item && this.item.id) {
|
||||||
|
const id = this.item.id
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/index/detils?id=${id}`
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.error('CarCard: item or item.id is missing', this.item)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// H5 下载:用 a 标签触发
|
||||||
|
downloadByAnchor(url, filename) {
|
||||||
|
try {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename || ''
|
||||||
|
a.target = '_blank'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
} catch (e) {
|
||||||
|
// 兜底:直接打开
|
||||||
|
if (typeof window !== 'undefined') window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
downloadpdf(item) {
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item.id }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadByAnchor(res.data.data.pdf_url, res.data.data.file_name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleToggleSave() {
|
||||||
|
const item = this.item
|
||||||
|
// if (item.pdf_src && item.pdf_src != '') {
|
||||||
|
// this.downloadpdf(item)
|
||||||
|
// } else {
|
||||||
|
// 让父组件统一弹出输入框(避免列表里每个卡片都渲染一个 popup)
|
||||||
|
this.$emit('request-price', { item, index: this.index })
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
buildShareLink(id) {
|
||||||
|
// 统一生成"详情页路径"
|
||||||
|
const path = `pages/index/detils?id=${id}&appid=${uni.getStorageSync('fsappid')}`
|
||||||
|
// #ifdef H5
|
||||||
|
try {
|
||||||
|
const origin = window.location.origin
|
||||||
|
// uni-app H5 默认 hash 路由
|
||||||
|
return `${origin}/${path}`
|
||||||
|
} catch (e) {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return path
|
||||||
|
},
|
||||||
|
isFeishuEnv() {
|
||||||
|
// 飞书/ Lark 客户端内置浏览器 UA 通常包含 Feishu / Lark
|
||||||
|
try {
|
||||||
|
const ua = (navigator.userAgent || '').toLowerCase()
|
||||||
|
return ua.includes('feishu') || ua.includes('lark')
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
feishuShare(payload) {
|
||||||
|
// 在飞书内优先使用 tt.share
|
||||||
|
try {
|
||||||
|
if (!this.isFeishuEnv()) return false
|
||||||
|
if (!window || !window.tt || !window.h5sdk) return false
|
||||||
|
// ready 后再调用
|
||||||
|
window.h5sdk.ready(() => {
|
||||||
|
// 优先使用 shareWebContent(文档推荐的 Web App 分享能力),不支持则降级到 share
|
||||||
|
if (typeof window.tt.shareWebContent === 'function') {
|
||||||
|
window.tt.shareWebContent({
|
||||||
|
title: payload.title,
|
||||||
|
content: payload.desc,
|
||||||
|
url: payload.link,
|
||||||
|
imageUrl: payload.imageUrl,
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({ title: '已唤起飞书分享', icon: 'none' })
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('feishu shareWebContent fail:', err)
|
||||||
|
uni.showToast({ title: '分享失败,可复制链接', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if (typeof window.tt.share === 'function') {
|
||||||
|
window.tt.share({
|
||||||
|
title: payload.title,
|
||||||
|
desc: payload.desc,
|
||||||
|
link: payload.link,
|
||||||
|
imageUrl: payload.imageUrl,
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({ title: '已唤起飞书分享', icon: 'none' })
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('feishu share fail:', err)
|
||||||
|
uni.showToast({ title: '分享失败,可复制链接', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw new Error('Feishu share api not available')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleShare() {
|
||||||
|
const item = this.item
|
||||||
|
const title = item.product_name || '车辆详情'
|
||||||
|
const link = this.buildShareLink(item.id)
|
||||||
|
const imageUrl = (item.images_pull && item.images_pull[0]) ? item.images_pull[0] : ''
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
// 小程序:打开系统分享面板(需要页面 onShareAppMessage 支持)
|
||||||
|
uni.showShareMenu({ withShareTicket: true })
|
||||||
|
uni.showToast({ title: '请使用右上角分享', icon: 'none' })
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
// 1) 飞书内:优先走飞书分享
|
||||||
|
const ok = this.feishuShare({
|
||||||
|
title,
|
||||||
|
desc: title,
|
||||||
|
link,
|
||||||
|
imageUrl
|
||||||
|
})
|
||||||
|
if (ok) return
|
||||||
|
|
||||||
|
// H5:优先走 Web Share API
|
||||||
|
if (typeof navigator !== 'undefined' && navigator.share) {
|
||||||
|
navigator.share({ title, text: title, url: link }).catch(() => {})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 兜底:弹出操作并复制链接
|
||||||
|
uni.showActionSheet({
|
||||||
|
itemList: ['复制链接', '复制标题'],
|
||||||
|
success: (res) => {
|
||||||
|
if (res.tapIndex === 0) {
|
||||||
|
uni.setClipboardData({ data: link })
|
||||||
|
} else {
|
||||||
|
uni.setClipboardData({ data: title })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.heard{
|
||||||
|
padding: 5px 10px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.car-cards {
|
||||||
|
padding-bottom: 6rpx; // 预留右下角按钮空间,避免遮挡信息
|
||||||
|
border-radius: 18rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
margin-bottom: 18rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
.car-card {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
padding: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 方案A:卡片右下角悬浮操作区 */
|
||||||
|
.card-actions {
|
||||||
|
padding: 18rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 14rpx;
|
||||||
|
border-top: 1px solid #e1e1e1;
|
||||||
|
}
|
||||||
|
.actions-lift {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.right-btn {
|
||||||
|
display: flex;
|
||||||
|
gap: 14rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
box-shadow: 0 8rpx 18rpx rgba(0, 0, 0, 0.12);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn:active {
|
||||||
|
transform: scale(0.96);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumb {
|
||||||
|
width: 190rpx;
|
||||||
|
height: 140rpx;
|
||||||
|
border-radius: 14rpx;
|
||||||
|
background: #eef2f7;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 18rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row1 {
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
max-width: 420rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
font-size: 22rpx;
|
||||||
|
padding: 6rpx 12rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: rgba(255, 151, 47, 0.14);
|
||||||
|
color: #b45309;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row2,
|
||||||
|
.row3 {
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.k {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #6b7280;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #374151;
|
||||||
|
font-weight: 600;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -0,0 +1,445 @@
|
|||||||
|
<template>
|
||||||
|
<view class="car-card-pro">
|
||||||
|
<view class="heard">
|
||||||
|
<view class="" @click="handleCardTap">
|
||||||
|
编号:{{item.code?item.code:'~'}}
|
||||||
|
</view>
|
||||||
|
<view v-if="ismy">
|
||||||
|
<u-icon @click="editfn(item)" name="edit-pen-fill" size="25" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="car-card" @click="handleCardTap">
|
||||||
|
<image class="thumb" :src="item.images_pull[0]" mode="aspectFill" />
|
||||||
|
<view class="info">
|
||||||
|
<view class="row row1">
|
||||||
|
<text class="name u-line-1">{{ item.product_name }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="row row2">
|
||||||
|
<view class="kv">
|
||||||
|
<text class="k">车源地</text>
|
||||||
|
<text class="v u-line-1">{{ item.source_place }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="kv">
|
||||||
|
<text class="k">车身颜色</text>
|
||||||
|
<text class="v u-line-1">{{ item.body_color }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="row row3">
|
||||||
|
<view class="kv">
|
||||||
|
<text class="k">上牌时间</text>
|
||||||
|
<text class="v">{{ formatPlateTime(item.plate_time) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="kv">
|
||||||
|
<text class="k">里程</text>
|
||||||
|
<text class="v">{{ item.mileage }} <text v-if="item.mileage">Km</text> </text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 操作区 -->
|
||||||
|
<view class="card-actions">
|
||||||
|
<view class="actions-lift" @click="handleCardTap">
|
||||||
|
<text class="">创建时间:</text>
|
||||||
|
<text class="">{{ item.created_at }}</text>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="right-btn">
|
||||||
|
<view class="action-btn" @tap.stop="handleToggleSave">
|
||||||
|
<u-icon name="download" size="18" />
|
||||||
|
</view>
|
||||||
|
<view class="action-btn" @tap.stop="handleShare">
|
||||||
|
<u-icon name="share" size="18" />
|
||||||
|
</view>
|
||||||
|
<view class="action-btn" @tap.stop="handleSet(item)" v-if="item.status==1">
|
||||||
|
<u-icon name="setting" size="18" />
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CarCardPro',
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
ismy: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
default: -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 计算视频数量
|
||||||
|
videoCount() {
|
||||||
|
if (!this.item.intro_video) return 0
|
||||||
|
if (Array.isArray(this.item.intro_video)) {
|
||||||
|
return this.item.intro_video.filter(Boolean).length
|
||||||
|
}
|
||||||
|
if (typeof this.item.intro_video === 'string') {
|
||||||
|
return this.item.intro_video.split(',').filter(s => s.trim()).length
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
},
|
||||||
|
// 计算FAQ数量
|
||||||
|
faqCount() {
|
||||||
|
if (!this.item.faqs) return 0
|
||||||
|
if (Array.isArray(this.item.faqs)) {
|
||||||
|
return this.item.faqs.filter(f => f.question && f.answer).length
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 跳转到编辑页面(供应商发布专用编辑页)
|
||||||
|
editfn(item) {
|
||||||
|
const id = item.id
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/index/publisheditPro?id=${id}`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
formatPlateTime(dateStr) {
|
||||||
|
return String(dateStr || '').slice(0, 7)
|
||||||
|
},
|
||||||
|
pdfchanges() {
|
||||||
|
this.$emit('pdfchange')
|
||||||
|
},
|
||||||
|
// 标记已售出
|
||||||
|
handleSet(item) {
|
||||||
|
const that = this
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确认标记已售出?',
|
||||||
|
success: res => {
|
||||||
|
if (res.confirm) {
|
||||||
|
request({
|
||||||
|
url: 'common/usedcardetail/update/status',
|
||||||
|
method: 'post',
|
||||||
|
data: { id: item.id, status: 2 }
|
||||||
|
}).then(res => {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
that.$emit('restchange')
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 跳转到专业详情页
|
||||||
|
handleCardTap() {
|
||||||
|
if (this.item && this.item.id) {
|
||||||
|
const id = this.item.id
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/index/detilsPro?id=${id}`
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.error('CarCardPro: item or item.id is missing', this.item)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// H5 下载
|
||||||
|
downloadByAnchor(url, filename) {
|
||||||
|
try {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename || ''
|
||||||
|
a.target = '_blank'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof window !== 'undefined') window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 下载PDF
|
||||||
|
downloadpdf(item) {
|
||||||
|
request({
|
||||||
|
url: 'common/usedcardetail/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item.id }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadByAnchor(res.data.data.pdf_url, res.data.data.file_name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 请求生成PDF
|
||||||
|
handleToggleSave() {
|
||||||
|
const item = this.item
|
||||||
|
this.$emit('request-price', { item, index: this.index })
|
||||||
|
},
|
||||||
|
// 生成分享链接
|
||||||
|
buildShareLink(id) {
|
||||||
|
const path = `pages/index/detilsPro?id=${id}&appid=${uni.getStorageSync('fsappid')}`
|
||||||
|
// #ifdef H5
|
||||||
|
try {
|
||||||
|
const origin = window.location.origin
|
||||||
|
return `${origin}/${path}`
|
||||||
|
} catch (e) {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return path
|
||||||
|
},
|
||||||
|
// 判断是否在飞书环境
|
||||||
|
isFeishuEnv() {
|
||||||
|
try {
|
||||||
|
const ua = (navigator.userAgent || '').toLowerCase()
|
||||||
|
return ua.includes('feishu') || ua.includes('lark')
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 飞书分享
|
||||||
|
feishuShare(payload) {
|
||||||
|
try {
|
||||||
|
if (!this.isFeishuEnv()) return false
|
||||||
|
if (!window || !window.tt || !window.h5sdk) return false
|
||||||
|
window.h5sdk.ready(() => {
|
||||||
|
if (typeof window.tt.shareWebContent === 'function') {
|
||||||
|
window.tt.shareWebContent({
|
||||||
|
title: payload.title,
|
||||||
|
content: payload.desc,
|
||||||
|
url: payload.link,
|
||||||
|
imageUrl: payload.imageUrl,
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({ title: '已唤起飞书分享', icon: 'none' })
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('feishu shareWebContent fail:', err)
|
||||||
|
uni.showToast({ title: '分享失败,可复制链接', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if (typeof window.tt.share === 'function') {
|
||||||
|
window.tt.share({
|
||||||
|
title: payload.title,
|
||||||
|
desc: payload.desc,
|
||||||
|
link: payload.link,
|
||||||
|
imageUrl: payload.imageUrl,
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({ title: '已唤起飞书分享', icon: 'none' })
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('feishu share fail:', err)
|
||||||
|
uni.showToast({ title: '分享失败,可复制链接', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 分享处理
|
||||||
|
handleShare() {
|
||||||
|
const item = this.item
|
||||||
|
const title = item.product_name || '车辆详情'
|
||||||
|
const link = this.buildShareLink(item.id)
|
||||||
|
const imageUrl = (item.images_pull && item.images_pull[0]) ? item.images_pull[0] : ''
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
uni.showShareMenu({ withShareTicket: true })
|
||||||
|
uni.showToast({ title: '请使用右上角分享', icon: 'none' })
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
const ok = this.feishuShare({
|
||||||
|
title,
|
||||||
|
desc: title,
|
||||||
|
link,
|
||||||
|
imageUrl
|
||||||
|
})
|
||||||
|
if (ok) return
|
||||||
|
|
||||||
|
if (typeof navigator !== 'undefined' && navigator.share) {
|
||||||
|
navigator.share({ title, text: title, url: link }).catch(() => {})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
uni.showActionSheet({
|
||||||
|
itemList: ['复制链接', '复制标题'],
|
||||||
|
success: (res) => {
|
||||||
|
if (res.tapIndex === 0) {
|
||||||
|
uni.setClipboardData({ data: link })
|
||||||
|
} else {
|
||||||
|
uni.setClipboardData({ data: title })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.heard {
|
||||||
|
padding: 5px 10px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-card-pro {
|
||||||
|
padding-bottom: 6rpx;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
background: linear-gradient(135deg, #fff 0%, #f8f9ff 100%);
|
||||||
|
// box-shadow: 0 10rpx 30rpx rgba(46, 108, 246, 0.12);
|
||||||
|
margin-bottom: 18rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid rgba(46, 108, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-card {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
padding: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions {
|
||||||
|
padding: 18rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 14rpx;
|
||||||
|
border-top: 1px solid #e1e1e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions-lift {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-btn {
|
||||||
|
display: flex;
|
||||||
|
gap: 14rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
box-shadow: 0 8rpx 18rpx rgba(0, 0, 0, 0.12);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn:active {
|
||||||
|
transform: scale(0.96);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumb {
|
||||||
|
width: 190rpx;
|
||||||
|
height: 140rpx;
|
||||||
|
border-radius: 14rpx;
|
||||||
|
background: #eef2f7;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 18rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row1 {
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
max-width: 280rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row2,
|
||||||
|
.row3 {
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row3 {
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特性标签行
|
||||||
|
.row4 {
|
||||||
|
gap: 12rpx;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-tag {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6rpx;
|
||||||
|
padding: 6rpx 12rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background: rgba(46, 108, 246, 0.08);
|
||||||
|
|
||||||
|
.tag-text {
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #2E6CF6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
background: rgba(255, 151, 47, 0.08);
|
||||||
|
|
||||||
|
.tag-text {
|
||||||
|
color: #FF972F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-text-empty {
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #999;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.k {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #6b7280;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #374151;
|
||||||
|
font-weight: 600;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
<template>
|
||||||
|
<view class="custom-tabbar" :style="{ paddingBottom: safeAreaInsets.bottom + 'px' }">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in tabList"
|
||||||
|
:key="index"
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: current === index }"
|
||||||
|
@tap="switchTab(item, index)"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
class="tab-icon"
|
||||||
|
:src="current === index ? item.selectedIconPath : item.iconPath"
|
||||||
|
mode="aspectFit"
|
||||||
|
/>
|
||||||
|
<text class="tab-text">{{ item.text }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getVisibleTabBar, getCurrentTabIndex, getUserRole } from '@/common/tabbar.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CustomTabBar',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
current: 0,
|
||||||
|
safeAreaInsets: {
|
||||||
|
bottom: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
tabList() {
|
||||||
|
// 根据权限获取可见的 tabbar 列表
|
||||||
|
const userRole = getUserRole()
|
||||||
|
return getVisibleTabBar(userRole)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.updateCurrent()
|
||||||
|
this.initSafeArea()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
// 页面显示时更新当前 tab 索引
|
||||||
|
this.updateCurrent()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 监听 tabList 变化,当角色改变导致 tabbar 列表变化时,更新当前索引
|
||||||
|
tabList: {
|
||||||
|
handler() {
|
||||||
|
this.updateCurrent()
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initSafeArea() {
|
||||||
|
// 获取安全区域信息(适配 iPhone X 等)
|
||||||
|
// #ifdef APP-PLUS || H5
|
||||||
|
try {
|
||||||
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
|
this.safeAreaInsets = systemInfo.safeAreaInsets || { bottom: 0 }
|
||||||
|
} catch (e) {
|
||||||
|
this.safeAreaInsets = { bottom: 0 }
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
updateCurrent() {
|
||||||
|
const pages = getCurrentPages()
|
||||||
|
if (pages.length === 0) return
|
||||||
|
|
||||||
|
const currentPage = pages[pages.length - 1]
|
||||||
|
const currentPath = currentPage.route || currentPage.$route?.path || ''
|
||||||
|
const index = getCurrentTabIndex(currentPath)
|
||||||
|
// 如果当前页面不在可见的 tabbar 列表中,保持当前索引或设为 0
|
||||||
|
this.current = index >= 0 ? index : 0
|
||||||
|
},
|
||||||
|
switchTab(item, index) {
|
||||||
|
if (this.current === index) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.switchTab({
|
||||||
|
url: '/' + item.pagePath,
|
||||||
|
fail: (err) => {
|
||||||
|
// 如果 switchTab 失败,可能是该页面不在 tabBar 中,使用 navigateTo
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/' + item.pagePath,
|
||||||
|
fail: () => {
|
||||||
|
console.error('导航失败:', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.custom-tabbar {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 100rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-top: 1px solid #e5e5e5;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
z-index: 999;
|
||||||
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
.tab-text {
|
||||||
|
color: #3F435B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-icon {
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #7A7E83;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
<template>
|
||||||
|
<view class="main">
|
||||||
|
<!-- <view class="input" :style="disabled?'background-color:#f5f7fa':''"> -->
|
||||||
|
<view class="input">
|
||||||
|
<!-- <input @click="showModal" v-model="_value" :style="disabled?'color:#c0c4cc':''" :placeholder="placeholder" disabled/> -->
|
||||||
|
<input @click="showModal" v-model="_value" :placeholder="placeholder" disabled/>
|
||||||
|
<text v-if="clearable&&!disabled" @click="empty" class="selectIcon iconcross"></text>
|
||||||
|
</view>
|
||||||
|
<view class="select-modal" :class="isShowModal?'show':''" @tap="hideModal">
|
||||||
|
<view class="select-dialog" @tap.stop="" :style="{backgroundColor:bgColor}">
|
||||||
|
<view class="select-bar bg-white">
|
||||||
|
<view class="action text-blue" @tap="cancelClick">{{cancelText}}</view>
|
||||||
|
<view class="action text-green" @tap="confirmClick">{{confirmText}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="select-content">
|
||||||
|
<view class="select-item" v-for="(item,index) in list" :key="index"
|
||||||
|
:style="valueIndexOf(item)?'color:'+selectColor+';background-color:'+selectBgColor+';':'color:'+color+';'"
|
||||||
|
@click="select(item)">
|
||||||
|
<view class="title">{{getLabelKeyValue(item)}}</view>
|
||||||
|
<text class="selectIcon icongou" v-if="valueIndexOf(item)"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isShowModal:false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value:{
|
||||||
|
type:[Number,String,Array,Object],
|
||||||
|
default:null
|
||||||
|
},
|
||||||
|
placeholder:{ // 占位符
|
||||||
|
default: "",
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
multiple:{ // 是否多选
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
default: () => [],
|
||||||
|
type: Array
|
||||||
|
},
|
||||||
|
valueKey:{ // 指定list中valueKey的值作为下拉框绑定内容
|
||||||
|
default: 'value',
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
labelKey:{ // 指定list中labelKey的值作为下拉框显示内容
|
||||||
|
default: 'label',
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
clearable:{
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
cancelText:{
|
||||||
|
default: "取消",
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
confirmText:{
|
||||||
|
default: "确定",
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
color:{
|
||||||
|
default: "#000000",
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
selectColor:{
|
||||||
|
default: "#0081ff",
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
bgColor:{
|
||||||
|
default: "#F1F1F1",
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
selectBgColor:{
|
||||||
|
default: "#FFFFFF",
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
_value: {
|
||||||
|
get() {
|
||||||
|
return this.get_value(this.value);
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('change', val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
get_value(val){ // 将数组值转换为以,隔开的字符串
|
||||||
|
if(val || val===0){
|
||||||
|
if(Array.isArray(val)){
|
||||||
|
let chooseAttr = []
|
||||||
|
val.forEach(item=>{
|
||||||
|
let choose = this.list.find(temp => {
|
||||||
|
let val_val = this.getValueKeyValue(temp)
|
||||||
|
return item == val_val
|
||||||
|
})
|
||||||
|
chooseAttr.push(choose)
|
||||||
|
})
|
||||||
|
let values = chooseAttr.map(temp => this.getLabelKeyValue(temp)).join(',')
|
||||||
|
return values
|
||||||
|
} else {
|
||||||
|
let choose = this.list.find(temp => {
|
||||||
|
let val_val = this.getValueKeyValue(temp)
|
||||||
|
return val == val_val
|
||||||
|
})
|
||||||
|
return this.getLabelKeyValue(choose)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
select(item){ // 点击选项
|
||||||
|
let val = this.getValueKeyValue(item);
|
||||||
|
if(this.multiple){
|
||||||
|
let _value = this.value;
|
||||||
|
let index = _value.indexOf(val);
|
||||||
|
if(index!=-1){
|
||||||
|
_value.splice(index,1)
|
||||||
|
this.$emit('change', _value)
|
||||||
|
} else {
|
||||||
|
_value.push(val)
|
||||||
|
this.$emit('change', _value)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$emit('change', val)
|
||||||
|
this.hideModal()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueIndexOf(item){
|
||||||
|
let val = this.getValueKeyValue(item);
|
||||||
|
if(Array.isArray(this.value)){
|
||||||
|
return this.value.indexOf(val)!=-1
|
||||||
|
} else {
|
||||||
|
return this.value == val
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getLabelKeyValue(item){ // 获取label
|
||||||
|
return item[this.labelKey]
|
||||||
|
},
|
||||||
|
getValueKeyValue(item){ // 获取value
|
||||||
|
return item[this.valueKey]
|
||||||
|
},
|
||||||
|
empty(){ // 清空
|
||||||
|
if(this.multiple){
|
||||||
|
this.$emit('change', [])
|
||||||
|
} else {
|
||||||
|
this.$emit('change', '')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelClick(){ // 点击取消
|
||||||
|
this.$emit('cancel', this._value)
|
||||||
|
this.hideModal()
|
||||||
|
},
|
||||||
|
confirmClick(){ // 点击确定
|
||||||
|
this.$emit('confirm', this._value)
|
||||||
|
this.hideModal()
|
||||||
|
},
|
||||||
|
showModal(){ // 显示model
|
||||||
|
if(!this.disabled){
|
||||||
|
this.isShowModal = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideModal(){ // 隐藏model
|
||||||
|
this.isShowModal = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
@font-face {font-family: "selectIcon";
|
||||||
|
src: url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.eot?t=1590375117208'); /* IE9 */
|
||||||
|
src: url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.eot?t=1590375117208#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||||
|
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAMEAAsAAAAABvQAAAK4AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqBRIFCATYCJAMMCwgABCAFhQUHNRsfBsg+QCa3uoO0oAJTMwhxVu965keqWBy1hkbwtfzWb2Z279/shRhJisKF6FApKLI7oyBbpAaHo3w24k+ca9EUJbDmjaeznUdZ/FOUlkWdJ33rizZY/Pw6J5Xw0qKYxHTMesePHVT6EFpaC4zV70sKi2bYgNPc1w0WHnDVC/e/UnNTgyP+4Jq6BBpIHoisgypLaIAFEtU0wgeaIG8Yu4nAIZwnUK1QgFfOT6nUUoBpgXjj2lqplTMpiuXtCW3N2iK+aPTS2/Qdnzny8d+5IEiaDMy99exklra//FrKnX48pChmgrq5QcYRQCEe17ruqgqLAKv8WntwqwhpLms/nB5yW/iHRxJEC0QOgT3NnfgF01NBKvOuIzNoZdh5gJuAeGrsozE8vOJ7u5D832oz55039W5G+S52K0H+zNf1TJz07k26kqoQybRfwVFV4rjDS/K8EXUyuF1cXnT3weKS9Rvdm/xe7h8oA1hLwOR18R+Y4n4zwpr4z5SU089Vc+cpfWL+mn5APmT3Z39jeOs/GbWjK+DnmsuL/u6ehMX4j4yedSVkAUUuPh3TY022MtKZUEOtPqCb8Bkvnr5XT6imU0gGrEJW7aAL/gw0OhegVV2F6pC7uTOppirKIA4MFQhTrpCM+AbZlDu64L/QmAkQWlMhQXU75D07O9Gtl0PUYjTBLyAzOLNQYtypIEEjvsXtBLQTooV2nrQrGEau2gKmZlR4L8gwnGtBJbUn1diCOOQUnEkTkRAOeci9KHOQxvFro+tx3ZcGAaeljstCSBNDJuArgIyBYyy6OdZxAhHIELu1IC9AtgShCVtLltEKrSff1XoHJo3RC33hM63o3j6pSNkmqmIWEAtxFHB2OwoRBAfyeqE3r2ogHeF42dBhs7gvf7CukH5MmlUGOCpHihxFfs6TehDyKCqVAA==') format('woff2'),
|
||||||
|
url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.woff?t=1590375117208') format('woff'),
|
||||||
|
url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.ttf?t=1590375117208') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
|
||||||
|
url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.svg?t=1590375117208#selectIcon') format('svg'); /* iOS 4.1- */
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectIcon {
|
||||||
|
font-family: "selectIcon" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icongou:before {
|
||||||
|
content: "\e61c";
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconcross:before {
|
||||||
|
content: "\e61a";
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.main{
|
||||||
|
font-size: 28rpx;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.bg-white{
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
.text-blue{
|
||||||
|
color:#929292;
|
||||||
|
}
|
||||||
|
.text-green{
|
||||||
|
color:#3c9cff;
|
||||||
|
}
|
||||||
|
.input {
|
||||||
|
display: flex;
|
||||||
|
align-items:center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
// height: 60rpx;
|
||||||
|
// padding: 10rpx 20rpx;
|
||||||
|
// border-radius: 10rpx;
|
||||||
|
// border-style: solid;
|
||||||
|
// border-width: 1rpx;
|
||||||
|
// border-color: rgba(0, 0, 0, 0.1);
|
||||||
|
input{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.select-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 9999;
|
||||||
|
opacity: 0;
|
||||||
|
outline: 0;
|
||||||
|
text-align: center;
|
||||||
|
-ms-transform: scale(1.185);
|
||||||
|
transform: scale(1.185);
|
||||||
|
backface-visibility: hidden;
|
||||||
|
perspective: 2000rpx;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
transition: all 0.3s ease-in-out 0s;
|
||||||
|
pointer-events: none;
|
||||||
|
margin-bottom: -1000rpx;
|
||||||
|
&::before {
|
||||||
|
content: "\200B";
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.select-dialog {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 0;
|
||||||
|
// border-radius: 10px 10px 0px 0px;
|
||||||
|
.select-content{
|
||||||
|
// background-color: #F1F1F1;
|
||||||
|
max-height: 440rpx;
|
||||||
|
overflow:auto;
|
||||||
|
.select-item{
|
||||||
|
padding:30rpx 20rpx;
|
||||||
|
display: flex;
|
||||||
|
.title{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.select-modal.show {
|
||||||
|
opacity: 1;
|
||||||
|
transition-duration: 0.3s;
|
||||||
|
-ms-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
pointer-events: auto;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.select-bar {
|
||||||
|
padding: 0 20rpx;
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 80rpx;
|
||||||
|
justify-content: space-between;
|
||||||
|
.action {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
<template>
|
||||||
|
<view class="custom-tabbar" :style="{ paddingBottom: safeAreaInsets.bottom + 'px' }">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in tabList"
|
||||||
|
:key="index"
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: current === index }"
|
||||||
|
@tap="switchTab(item, index)"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
class="tab-icon"
|
||||||
|
:src="current === index ? item.selectedIconPath : item.iconPath"
|
||||||
|
mode="aspectFit"
|
||||||
|
/>
|
||||||
|
<text class="tab-text">{{ item.text }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getVisibleTabBar, getCurrentTabIndex, getUserRole } from '@/common/tabbar.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CustomTabBar',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
current: 0,
|
||||||
|
safeAreaInsets: {
|
||||||
|
bottom: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
tabList() {
|
||||||
|
// 根据权限获取可见的 tabbar 列表
|
||||||
|
const userRole = getUserRole()
|
||||||
|
return getVisibleTabBar(userRole)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.initSafeArea()
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.updateCurrent()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
// 页面显示时更新当前 tab 索引
|
||||||
|
this.updateCurrent()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 监听 tabList 变化,当角色改变导致 tabbar 列表变化时,更新当前索引
|
||||||
|
tabList: {
|
||||||
|
handler() {
|
||||||
|
this.updateCurrent()
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initSafeArea() {
|
||||||
|
// 获取安全区域信息(适配 iPhone X 等)
|
||||||
|
// #ifdef APP-PLUS || H5
|
||||||
|
try {
|
||||||
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
|
this.safeAreaInsets = systemInfo.safeAreaInsets || { bottom: 0 }
|
||||||
|
} catch (e) {
|
||||||
|
this.safeAreaInsets = { bottom: 0 }
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
updateCurrent() {
|
||||||
|
const pages = getCurrentPages()
|
||||||
|
if (pages.length === 0) return
|
||||||
|
|
||||||
|
const currentPage = pages[pages.length - 1]
|
||||||
|
const currentPath = currentPage.route || currentPage.$route?.path || ''
|
||||||
|
const index = getCurrentTabIndex(currentPath)
|
||||||
|
// 如果当前页面不在可见的 tabbar 列表中,保持当前索引或设为 0
|
||||||
|
this.current = index >= 0 ? index : 0
|
||||||
|
},
|
||||||
|
switchTab(item, index) {
|
||||||
|
if (this.current === index) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.switchTab({
|
||||||
|
url: '/' + item.pagePath,
|
||||||
|
fail: (err) => {
|
||||||
|
// 如果 switchTab 失败,可能是该页面不在 tabBar 中,使用 navigateTo
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/' + item.pagePath,
|
||||||
|
fail: () => {
|
||||||
|
console.error('导航失败:', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.custom-tabbar {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 100rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-top: 1px solid #e5e5e5;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
z-index: 999;
|
||||||
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
.tab-text {
|
||||||
|
color: #3F435B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-icon {
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #7A7E83;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script>
|
||||||
|
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||||
|
CSS.supports('top: constant(a)'))
|
||||||
|
document.write(
|
||||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||||
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||||
|
</script>
|
||||||
|
<title></title>
|
||||||
|
<script src="/static/image-resize-3.0.1.min.js"></script>
|
||||||
|
<script src="/static/quill-1.3.7.min.js"></script>
|
||||||
|
<!--preload-links-->
|
||||||
|
<!--app-context-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"><!--app-html--></div>
|
||||||
|
<script type="module" src="/main.js"></script>
|
||||||
|
<!-- 飞书二维码SDK -->
|
||||||
|
<script
|
||||||
|
src="https://lf-package-cn.feishucdn.com/obj/feishu-static/lark/passport/qrcode/LarkSSOSDKWebQRCode-1.0.3.js"
|
||||||
|
onload="console.log('[Feishu SDK] Script loaded successfully')"
|
||||||
|
onerror="console.error('[Feishu SDK] Script failed to load')"
|
||||||
|
></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
module.exports = {
|
||||||
|
testTimeout: 20000,
|
||||||
|
reporters: [
|
||||||
|
'default'
|
||||||
|
],
|
||||||
|
watchPathIgnorePatterns: ['/node_modules/', '/dist/', '/.git/'],
|
||||||
|
moduleFileExtensions: ['js', 'json'],
|
||||||
|
rootDir: __dirname,
|
||||||
|
testMatch: ["<rootDir>/pages/**/*test.[jt]s?(x)"],
|
||||||
|
testPathIgnorePatterns: ['/node_modules/']
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import App from './App'
|
||||||
|
import store from './store'
|
||||||
|
|
||||||
|
// #ifndef VUE3
|
||||||
|
import Vue from 'vue'
|
||||||
|
import uView from './uni_modules/uview-ui';
|
||||||
|
Vue.use(uView);
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
Vue.prototype.$store = store
|
||||||
|
Vue.prototype.$adpid = "1111111111"
|
||||||
|
Vue.prototype.$backgroundAudioData = {
|
||||||
|
playing: false,
|
||||||
|
playTime: 0,
|
||||||
|
formatedPlayTime: '00:00:00'
|
||||||
|
}
|
||||||
|
|
||||||
|
// i18n部分的配置
|
||||||
|
// 引入语言包,注意路径
|
||||||
|
import Chinese from '@/common/locales/zh.js';
|
||||||
|
import English from '@/common/locales/en.js';
|
||||||
|
import Eyu from '@/common/locales/ru.js';
|
||||||
|
|
||||||
|
// 引入并使用vue-i18n
|
||||||
|
import VueI18n from 'vue-i18n'
|
||||||
|
Vue.use(VueI18n)
|
||||||
|
console.log(uni.getLocale())
|
||||||
|
let i18nConfig = {
|
||||||
|
locale: uni.getStorageSync('i18locale')?uni.getStorageSync('i18locale'):'zh',// 获取已设置的语言
|
||||||
|
messages: {
|
||||||
|
// 这里的属性名是任意的,您也可以把zh设置为cn等,只是后续切换语言时
|
||||||
|
// 要标识这里的语言属性,如:this.$i18n.locale = zh|en|cn|xxx
|
||||||
|
'zh': Chinese,
|
||||||
|
'en': English,
|
||||||
|
'ru': Eyu,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 构造i18n对象
|
||||||
|
const i18n = new VueI18n({
|
||||||
|
// 默认语言,这里的local属性,对应message中的cn、en属性
|
||||||
|
locale:uni.getStorageSync('i18locale')?uni.getStorageSync('i18locale'):'zh',
|
||||||
|
// 引入语言文件
|
||||||
|
messages: {
|
||||||
|
// 这里的属性名是任意的,您也可以把zh设置为cn等,只是后续切换语言时
|
||||||
|
// 要标识这里的语言属性,如:this.$i18n.locale = zh|en|cn|xxx
|
||||||
|
'zh': Chinese,
|
||||||
|
'en': English,
|
||||||
|
'ru': Eyu,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
App.mpType = 'app'
|
||||||
|
Vue.prototype._i18n = i18n
|
||||||
|
const app = new Vue({
|
||||||
|
store,
|
||||||
|
i18n,
|
||||||
|
...App
|
||||||
|
})
|
||||||
|
app.$mount()
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef VUE3
|
||||||
|
import {
|
||||||
|
createSSRApp
|
||||||
|
} from 'vue'
|
||||||
|
import * as Pinia from 'pinia';
|
||||||
|
import Vuex from "vuex";
|
||||||
|
export function createApp() {
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
app.use(store)
|
||||||
|
app.use(Pinia.createPinia());
|
||||||
|
app.config.globalProperties.$adpid = "1111111111"
|
||||||
|
app.config.globalProperties.$backgroundAudioData = {
|
||||||
|
playing: false,
|
||||||
|
playTime: 0,
|
||||||
|
formatedPlayTime: '00:00:00'
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
app,
|
||||||
|
Vuex, // 如果 nvue 使用 vuex 的各种map工具方法时,必须 return Vuex
|
||||||
|
Pinia // 此处必须将 Pinia 返回
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"name" : "Used Car",
|
||||||
|
"appid" : "__UNI__C9A60ED",
|
||||||
|
"description" : "应用描述",
|
||||||
|
"versionName" : "1.0.0",
|
||||||
|
"versionCode" : "100",
|
||||||
|
"transformPx" : false,
|
||||||
|
"locale" : "zh", // 设置默认语言,
|
||||||
|
"app-plus" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"nvueCompiler" : "uni-app",
|
||||||
|
"nvueStyleCompiler" : "uni-app",
|
||||||
|
"compilerVersion" : 3,
|
||||||
|
"nvueLaunchMode" : "fast",
|
||||||
|
"splashscreen" : {
|
||||||
|
"alwaysShowBeforeRender" : true,
|
||||||
|
"waiting" : true,
|
||||||
|
"autoclose" : true,
|
||||||
|
"delay" : 0
|
||||||
|
},
|
||||||
|
"modules" : {
|
||||||
|
"OAuth" : {},
|
||||||
|
"Payment" : {},
|
||||||
|
"Push" : {},
|
||||||
|
"Share" : {},
|
||||||
|
"Speech" : {},
|
||||||
|
"VideoPlayer" : {}
|
||||||
|
},
|
||||||
|
"distribute" : {
|
||||||
|
"android" : {
|
||||||
|
"permissions" : [
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_MOCK_LOCATION\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.GET_TASKS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_SMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.SEND_SMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WRITE_SMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.RECEIVE_USER_PRESENT\"/>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ios" : {
|
||||||
|
"UIBackgroundModes" : [ "audio" ],
|
||||||
|
"urlschemewhitelist" : [ "baidumap", "iosamap" ],
|
||||||
|
"dSYMs" : false
|
||||||
|
},
|
||||||
|
"sdkConfigs" : {
|
||||||
|
"speech" : {
|
||||||
|
"ifly" : {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"orientation" : [ "portrait-primary" ]
|
||||||
|
},
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"quickapp" : {},
|
||||||
|
"quickapp-native" : {
|
||||||
|
"icon" : "/static/logo.png",
|
||||||
|
"package" : "com.example.demo",
|
||||||
|
"features" : [
|
||||||
|
{
|
||||||
|
"name" : "system.clipboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"quickapp-webview" : {
|
||||||
|
"icon" : "/static/logo.png",
|
||||||
|
"package" : "com.example.demo",
|
||||||
|
"minPlatformVersion" : 1070,
|
||||||
|
"versionName" : "1.0.0",
|
||||||
|
"versionCode" : 100
|
||||||
|
},
|
||||||
|
"mp-weixin" : {
|
||||||
|
"appid" : "wx62c3f16d37f2c2a2",
|
||||||
|
"setting" : {
|
||||||
|
"urlCheck" : false,
|
||||||
|
"minified" : true,
|
||||||
|
"postcss" : true
|
||||||
|
},
|
||||||
|
"usingComponents" : true,
|
||||||
|
"permission" : {},
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mp-alipay" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mp-baidu" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
},
|
||||||
|
"dynamicLib" : {
|
||||||
|
"editorLib" : {
|
||||||
|
"provider" : "swan-editor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mp-toutiao" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mp-jd" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"h5" : {
|
||||||
|
"template" : "template.h5.html",
|
||||||
|
"router" : {
|
||||||
|
"mode" : "history",
|
||||||
|
"base" : ""
|
||||||
|
},
|
||||||
|
"sdkConfigs" : {
|
||||||
|
"maps" : {
|
||||||
|
"qqmap" : {
|
||||||
|
"key" : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"async" : {
|
||||||
|
"timeout" : 20000
|
||||||
|
},
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vueVersion" : "2",
|
||||||
|
"mp-kuaishou" : {
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mp-lark" : {
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mp-qq" : {
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"quickapp-webview-huawei" : {
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"quickapp-webview-union" : {
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniStatistics" : {
|
||||||
|
"version" : "2",
|
||||||
|
"enable" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,347 @@
|
|||||||
|
{
|
||||||
|
"name": "hello-uniapp",
|
||||||
|
"version": "3.4.7",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "hello-uniapp",
|
||||||
|
"version": "3.4.7",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"vue-i18n": "^11.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-string-parser": {
|
||||||
|
"version": "7.25.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
|
||||||
|
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-validator-identifier": {
|
||||||
|
"version": "7.25.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
|
||||||
|
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/parser": {
|
||||||
|
"version": "7.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
|
||||||
|
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.27.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"parser": "bin/babel-parser.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/types": {
|
||||||
|
"version": "7.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
|
||||||
|
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-string-parser": "^7.25.9",
|
||||||
|
"@babel/helper-validator-identifier": "^7.25.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@intlify/core-base": {
|
||||||
|
"version": "11.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.1.3.tgz",
|
||||||
|
"integrity": "sha512-cMuHunYO7LE80azTitcvEbs1KJmtd6g7I5pxlApV3Jo547zdO3h31/0uXpqHc+Y3RKt1wo2y68RGSx77Z1klyA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@intlify/message-compiler": "11.1.3",
|
||||||
|
"@intlify/shared": "11.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/kazupon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@intlify/message-compiler": {
|
||||||
|
"version": "11.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.1.3.tgz",
|
||||||
|
"integrity": "sha512-7rbqqpo2f5+tIcwZTAG/Ooy9C8NDVwfDkvSeDPWUPQW+Dyzfw2o9H103N5lKBxO7wxX9dgCDjQ8Umz73uYw3hw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@intlify/shared": "11.1.3",
|
||||||
|
"source-map-js": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/kazupon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@intlify/shared": {
|
||||||
|
"version": "11.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.1.3.tgz",
|
||||||
|
"integrity": "sha512-pTFBgqa/99JRA2H1qfyqv97MKWJrYngXBA/I0elZcYxvJgcCw3mApAoPW3mJ7vx3j+Ti0FyKUFZ4hWxdjKaxvA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/kazupon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/@vue/compiler-core": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/parser": "^7.25.3",
|
||||||
|
"@vue/shared": "3.5.13",
|
||||||
|
"entities": "^4.5.0",
|
||||||
|
"estree-walker": "^2.0.2",
|
||||||
|
"source-map-js": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/compiler-dom": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/compiler-core": "3.5.13",
|
||||||
|
"@vue/shared": "3.5.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/compiler-sfc": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/parser": "^7.25.3",
|
||||||
|
"@vue/compiler-core": "3.5.13",
|
||||||
|
"@vue/compiler-dom": "3.5.13",
|
||||||
|
"@vue/compiler-ssr": "3.5.13",
|
||||||
|
"@vue/shared": "3.5.13",
|
||||||
|
"estree-walker": "^2.0.2",
|
||||||
|
"magic-string": "^0.30.11",
|
||||||
|
"postcss": "^8.4.48",
|
||||||
|
"source-map-js": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/compiler-ssr": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/compiler-dom": "3.5.13",
|
||||||
|
"@vue/shared": "3.5.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/devtools-api": {
|
||||||
|
"version": "6.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
|
||||||
|
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
|
||||||
|
},
|
||||||
|
"node_modules/@vue/reactivity": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/shared": "3.5.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/runtime-core": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/reactivity": "3.5.13",
|
||||||
|
"@vue/shared": "3.5.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/runtime-dom": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/reactivity": "3.5.13",
|
||||||
|
"@vue/runtime-core": "3.5.13",
|
||||||
|
"@vue/shared": "3.5.13",
|
||||||
|
"csstype": "^3.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/server-renderer": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/compiler-ssr": "3.5.13",
|
||||||
|
"@vue/shared": "3.5.13"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "3.5.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/shared": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/csstype": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/entities": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/estree-walker": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/magic-string": {
|
||||||
|
"version": "0.30.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
|
||||||
|
"integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nanoid": {
|
||||||
|
"version": "3.3.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||||
|
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"peer": true,
|
||||||
|
"bin": {
|
||||||
|
"nanoid": "bin/nanoid.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/picocolors": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/postcss": {
|
||||||
|
"version": "8.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
||||||
|
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/postcss/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "tidelift",
|
||||||
|
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"nanoid": "^3.3.8",
|
||||||
|
"picocolors": "^1.1.1",
|
||||||
|
"source-map-js": "^1.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^10 || ^12 || >=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/source-map-js": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vue": {
|
||||||
|
"version": "3.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz",
|
||||||
|
"integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/compiler-dom": "3.5.13",
|
||||||
|
"@vue/compiler-sfc": "3.5.13",
|
||||||
|
"@vue/runtime-dom": "3.5.13",
|
||||||
|
"@vue/server-renderer": "3.5.13",
|
||||||
|
"@vue/shared": "3.5.13"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vue-i18n": {
|
||||||
|
"version": "11.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.1.3.tgz",
|
||||||
|
"integrity": "sha512-Pcylh9z9S5+CJAqgbRZ3EKxFIBIrtY5YUppU722GIT65+Nukm0TCqiQegZnNLCZkXGthxe0cpqj0AoM51H+6Gw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@intlify/core-base": "11.1.3",
|
||||||
|
"@intlify/shared": "11.1.3",
|
||||||
|
"@vue/devtools-api": "^6.5.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/kazupon"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
{
|
||||||
|
"id": "hello-uniapp",
|
||||||
|
"name": "hello-uniapp",
|
||||||
|
"displayName": "hello-uniapp 示例工程",
|
||||||
|
"version": "3.4.7",
|
||||||
|
"description": "uni-app 框架示例,一套代码,同时发行到iOS、Android、H5、小程序等多个平台,请使用手机扫码快速体验 uni-app 的强大功能",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": "https://github.com/dcloudio/hello-uniapp.git",
|
||||||
|
"keywords": [
|
||||||
|
"hello-uniapp",
|
||||||
|
"uni-app",
|
||||||
|
"uni-ui",
|
||||||
|
"示例工程"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/dcloudio/hello-uniapp/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/dcloudio/hello-uniapp#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"vue-i18n": "^11.1.3"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "",
|
||||||
|
"type": "uniapp-template-project"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y",
|
||||||
|
"alipay": "n"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y",
|
||||||
|
"app-harmony": "u",
|
||||||
|
"app-uvue": "u"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y",
|
||||||
|
"京东": "y",
|
||||||
|
"钉钉": "y",
|
||||||
|
"快手": "y",
|
||||||
|
"飞书": "y"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "y",
|
||||||
|
"联盟": "y"
|
||||||
|
},
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uni-app": {
|
||||||
|
"scripts": {
|
||||||
|
"mp-dingtalk": {
|
||||||
|
"title": "钉钉小程序",
|
||||||
|
"env": {
|
||||||
|
"UNI_PLATFORM": "mp-alipay"
|
||||||
|
},
|
||||||
|
"define": {
|
||||||
|
"MP-DINGTALK": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hello-uniapp-demo": {
|
||||||
|
"title": "hello-uniapp 演示网站",
|
||||||
|
"env": {
|
||||||
|
"UNI_PLATFORM": "h5"
|
||||||
|
},
|
||||||
|
"define": {
|
||||||
|
"H5-DEMO": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
{
|
||||||
|
"pages": [
|
||||||
|
// pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||||
|
|
||||||
|
{
|
||||||
|
"path" : "pages/login/index",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "Used Car",
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
"navigationStyle":"custom",// 去掉微信小程序顶部导航
|
||||||
|
"app-plus":{
|
||||||
|
"titleNView":false //去掉app+h5顶部导航
|
||||||
|
},
|
||||||
|
"mp-alipay": {
|
||||||
|
"transparentTitle": "always",
|
||||||
|
"titlePenetrate": "YES"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
"path": "pages/index/index",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "首页",
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
"navigationStyle":"custom",// 去掉微信小程序顶部导航
|
||||||
|
"app-plus":{
|
||||||
|
"titleNView":false //去掉app+h5顶部导航
|
||||||
|
},
|
||||||
|
"mp-alipay": {
|
||||||
|
"transparentTitle": "always",
|
||||||
|
"titlePenetrate": "YES"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/index/mine",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "我的",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/index/publish",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "发布",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/index/publishedit",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "编辑",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/index/detils",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "详情",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/index/changinfo",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "个人信息",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/index/myPublish",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "我的发布",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/index/myPublishpro",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "我的发布",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/login/feishu-callback",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "Used Car",
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
"navigationStyle":"custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/index/ywPublish",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/index/publishPro",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "发布",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/index/detilsPro",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "发布详情",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/index/publisheditPro",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "编辑发布",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"subPackages":[],
|
||||||
|
"globalStyle": {
|
||||||
|
"pageOrientation": "portrait",
|
||||||
|
"navigationBarTitleText": "Hello uniapp",
|
||||||
|
"navigationBarTextStyle": "white",
|
||||||
|
"navigationBarBackgroundColor": "#007AFF",
|
||||||
|
"backgroundColor": "#F8F8F8",
|
||||||
|
"backgroundColorTop": "#F4F5F6",
|
||||||
|
"backgroundColorBottom": "#F4F5F6",
|
||||||
|
"mp-360": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
},
|
||||||
|
"h5": {
|
||||||
|
"maxWidth": 1190,
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
"navigationBarBackgroundColor": "#F1F1F1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tabBar": {
|
||||||
|
"custom": true,
|
||||||
|
"color": "#7A7E83",
|
||||||
|
"selectedColor": "#3F435B",
|
||||||
|
"borderStyle": "white",
|
||||||
|
"backgroundColor": "#fff",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"pagePath": "pages/index/index",
|
||||||
|
"text": "首页"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/index/publish",
|
||||||
|
"text": "发布"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/index/publishPro",
|
||||||
|
"text": "发布"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/index/mine",
|
||||||
|
"text": "我的"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,279 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<uni-nav-bar leftText=" " :fixed="true" :border="false" leftIcon="back" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="个人信息"></uni-nav-bar>
|
||||||
|
<view class="content">
|
||||||
|
<view class="topimg">
|
||||||
|
<uni-file-picker fileMediatype="image" limit="1" :list-styles="imageStyles" :del-icon="false" disable-preview @select="select" @delete="delfn('picture')">
|
||||||
|
<image class="user" :src="userinfo.avatar_pull"mode=""></image>
|
||||||
|
</uni-file-picker>
|
||||||
|
<view>点击更换头像</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell1">
|
||||||
|
<view class="item">英文名</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入英文名" type="text" v-model="userinfo.name_en"></input>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell1">
|
||||||
|
<view class="item">手机号</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入手机号" type="number" v-model="userinfo.phone"></input>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-divider text=""></u-divider>
|
||||||
|
<view class="cell1">
|
||||||
|
<view class="item">邮箱</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入邮箱" type="text" v-model="userinfo.email"></input>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-divider text=""></u-divider>
|
||||||
|
<view class="cell1">
|
||||||
|
<view class="item">whatsapp</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入whatsapp" type="text" v-model="userinfo.whatsapp"></input>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-divider text=""></u-divider>
|
||||||
|
<view class="cell1">
|
||||||
|
<view class="item">二维码</view>
|
||||||
|
<view class="right">
|
||||||
|
<u-radio-group v-model="userinfo.social">
|
||||||
|
<u-radio name="微信" class="m-r-10">微信</u-radio>
|
||||||
|
<u-radio name="WhatsApp">WhatsApp</u-radio>
|
||||||
|
</u-radio-group>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell">
|
||||||
|
<view class="item">上传二维码</view>
|
||||||
|
<view class="right">
|
||||||
|
<uni-file-picker style="margin: 10px 0px;" fileMediatype="image" limit="1" :list-styles="imageStyles" :del-icon="false" disable-preview @select="selectewm" >
|
||||||
|
<image class="user" :src="userinfo.social_code_pull==null?'/static/image/mine/erwm.png':userinfo.social_code_pull " mode=""></image>
|
||||||
|
</uni-file-picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="foot">
|
||||||
|
<button class="btn" @click="bcFn">保存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { nextTick } from "vue"
|
||||||
|
import { request,showToast } from '@/api/apiT.js'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
imageStyles: {
|
||||||
|
border: true,
|
||||||
|
},
|
||||||
|
userinfo:{},
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.getinfo()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getinfo(){
|
||||||
|
var that= this;
|
||||||
|
request({
|
||||||
|
url:'common/user/info',
|
||||||
|
method:'get',
|
||||||
|
}).then(res => {
|
||||||
|
that.userinfo = res.data.data;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
uploadfn(imgUrl,name,name1){
|
||||||
|
const that = this
|
||||||
|
uni.showLoading({
|
||||||
|
title: '上传中'
|
||||||
|
});
|
||||||
|
uni.uploadFile({
|
||||||
|
url: 'https://userdcar-server.hnxinyouhe.com/upload?scene=usedCarimg',
|
||||||
|
filePath: imgUrl,
|
||||||
|
name: 'file',
|
||||||
|
header:{'Fdesk-Auth-Token': uni.getStorageSync('token'),'Fdesk-Login-Type': 'feishu','Fdesk-System-Code':'fdesk'},
|
||||||
|
success: (uploadFileRes) => {
|
||||||
|
const res = JSON.parse(uploadFileRes.data || '{}')
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title:res.message,
|
||||||
|
icon:'none'
|
||||||
|
})
|
||||||
|
if(res && res.data && res.data.file_name){
|
||||||
|
that.userinfo[name1] = res.data.file_url
|
||||||
|
that.userinfo[name] = res.data.file_name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => reject(err)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
selectewm(e){
|
||||||
|
const tempFilePaths = e.tempFilePaths;
|
||||||
|
const imgUrl=tempFilePaths[0]
|
||||||
|
this.uploadfn(imgUrl,'social_code','social_code_pull')
|
||||||
|
},
|
||||||
|
select(e){
|
||||||
|
const tempFilePaths = e.tempFilePaths;
|
||||||
|
const imgUrl=tempFilePaths[0]
|
||||||
|
this.uploadfn(imgUrl,'avatar','avatar_url')
|
||||||
|
},
|
||||||
|
leftClick(){
|
||||||
|
uni.navigateBack({})
|
||||||
|
},
|
||||||
|
bcFn(){
|
||||||
|
request({
|
||||||
|
url:'common/user/edit',
|
||||||
|
method:'POST',
|
||||||
|
data:{
|
||||||
|
avatar:this.userinfo.avatar,
|
||||||
|
phone:this.userinfo.phone,
|
||||||
|
email:this.userinfo.email,
|
||||||
|
whatsapp:this.userinfo.whatsapp,
|
||||||
|
social:this.userinfo.social,
|
||||||
|
social_code:this.userinfo.social_code,
|
||||||
|
name_en:this.userinfo.name_en
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
if(res.data.code ==0||res.data.code ==200){
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/index/mine',// 替换为你要跳转的页面路径
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.uni-file-picker {
|
||||||
|
margin-left: 33.3%;
|
||||||
|
}
|
||||||
|
.m-r-10{
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.uniui-right{
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
|
.u-divider{
|
||||||
|
margin: 0px 0px !important;
|
||||||
|
}
|
||||||
|
.arrowright{
|
||||||
|
margin-right: -15px;
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
.topimg{
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
padding: 20px 0px;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
.user{
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
}
|
||||||
|
.xj{
|
||||||
|
width: 60rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
position: absolute;
|
||||||
|
right: 46%;
|
||||||
|
top: 33%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cell1{
|
||||||
|
display: flex;
|
||||||
|
justify-content:space-between;
|
||||||
|
padding: 18px 20px;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 500;
|
||||||
|
.item{
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cell{
|
||||||
|
padding: 18px 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
.item{
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right{
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.select{
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.foot{
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 160rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
}
|
||||||
|
.btn{
|
||||||
|
background: #3F435B;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50px;
|
||||||
|
width: 84%;
|
||||||
|
margin: 20px 8%;
|
||||||
|
}
|
||||||
|
.addimg{
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
.actives{
|
||||||
|
background-color: #dfdfdf;
|
||||||
|
}
|
||||||
|
.text{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 10px 15px 0px;
|
||||||
|
.qd{
|
||||||
|
color: #3471FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.popup-content {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-list {
|
||||||
|
max-height: 400rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item {
|
||||||
|
padding: 20rpx;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,720 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<!-- 自定义导航(pages.json 里已设置 navigationStyle: custom) -->
|
||||||
|
<!-- <uni-nav-bar leftText=" " @clickLeft="goBack" leftIcon="back" :fixed="true" :border="false" color="#fff" backgroundColor="#3F435B" :statusBar="true" title="车辆详情"></uni-nav-bar> -->
|
||||||
|
<view class="content">
|
||||||
|
<!-- 基础信息卡片 -->
|
||||||
|
<view class="card">
|
||||||
|
<view class="heard">
|
||||||
|
<view class="">
|
||||||
|
编号:{{detail.code?detail.code:'~'}}
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<u-icon @click="openPriceDialog()" name="download" size="25" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="title-row">
|
||||||
|
<text class="name">{{ detail.product_name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="kv">
|
||||||
|
<!-- <view class="kv-item" @click="copyIfHas('车辆识别码', detail.vin)">
|
||||||
|
<text class="k">车辆识别码</text>
|
||||||
|
<text class="v ellipsis">{{ detail.vin }}</text>
|
||||||
|
<text class="copy" v-if="detail.vin">复制</text>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">车价(¥)</text>
|
||||||
|
<text class="v">{{ detail.price }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">车源地</text>
|
||||||
|
<text class="v">{{ detail.source_place}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- <view class="kv-item">
|
||||||
|
<text class="k">上牌地</text>
|
||||||
|
<text class="v">{{ detail.plate_place }}</text>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">上牌时间</text>
|
||||||
|
<text class="v">{{ detail.plate_time }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">排量</text>
|
||||||
|
<text class="v">{{ detail.displacement }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">里程</text>
|
||||||
|
<text class="v">{{ detail.mileage }}<text v-if="detail.mileage">Km</text></text>
|
||||||
|
</view>
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">马力</text>
|
||||||
|
<text class="v">{{ detail.power }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">车身颜色</text>
|
||||||
|
<text class="v">{{ detail.body_color }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">创建时间</text>
|
||||||
|
<text class="v">{{ detail.created_at }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 车况介绍 -->
|
||||||
|
<view class="card">
|
||||||
|
<view class="section-title">车况介绍</view>
|
||||||
|
<text class="desc" v-if="detail.condition_desc!=''">{{ detail.condition_desc }}</text>
|
||||||
|
<view class="noneview" v-else>
|
||||||
|
<img src="/static/image/none.png" alt="">
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<view class="hero">
|
||||||
|
<view class="section-title">产品图</view>
|
||||||
|
<!-- 有图:九宫格/多行平铺;无图:占位 -->
|
||||||
|
<view class="img-grid">
|
||||||
|
<image
|
||||||
|
v-for="(src, i) in detail.images_pull"
|
||||||
|
:key="i"
|
||||||
|
class="grid-img"
|
||||||
|
:src="src"
|
||||||
|
mode="aspectFill"
|
||||||
|
@click="previewImages(i)"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="hero">
|
||||||
|
<view class="section-title">附件</view>
|
||||||
|
<view v-if="detail.attachment_pull.length>0">
|
||||||
|
<view v-for="(file, i) in detail.attachment_pull" :key="i" class="fujian" @click="reviewFile(file)">
|
||||||
|
<p>{{file.name}}</p>
|
||||||
|
<view>查看</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="noneview" v-else>
|
||||||
|
<img src="/static/image/none.png" alt="">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<uni-popup ref="inputDialog" type="dialog">
|
||||||
|
<view class="price-dialog">
|
||||||
|
<view class="pd-title">设置价格</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">贸易条款</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<uni-data-select
|
||||||
|
v-model="priceForm.trade_term"
|
||||||
|
class="tradeTerm"
|
||||||
|
:localdata="tradeTermOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">价格</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<view class="pd-input-suffix-wrap">
|
||||||
|
<input
|
||||||
|
class="pd-input pd-input-price pd-input-with-suffix"
|
||||||
|
v-model="priceForm.price"
|
||||||
|
type="number"
|
||||||
|
inputmode="decimal"
|
||||||
|
placeholder="请输入数字"
|
||||||
|
@input="onPriceInput"
|
||||||
|
/>
|
||||||
|
<!-- 币种下拉:放在输入框内部右侧(无边框) -->
|
||||||
|
<view class="pd-currency-suffix">
|
||||||
|
<uni-data-select
|
||||||
|
v-model="priceForm.currency"
|
||||||
|
:localdata="currencyOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 语言单选 -->
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">语言</view>
|
||||||
|
<radio-group class="pd-radio-group" @change="onLangChange">
|
||||||
|
<label class="pd-radio" v-for="l in langOptions" :key="l.value">
|
||||||
|
<radio :value="l.value" :checked="priceForm.lang === l.value" />
|
||||||
|
<text class="pd-radio-text">{{ l.text }}</text>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<view class="pd-actions">
|
||||||
|
<view class="pd-btn pd-cancel" @tap="closePriceDialog">取消</view>
|
||||||
|
<view class="pd-btn pd-confirm" @tap="confirmPriceDialog">确认</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request, showToast } from '@/api/apiT.js'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
id: '',
|
||||||
|
appid: '',
|
||||||
|
detail: {},
|
||||||
|
currentImageIndex: 0,
|
||||||
|
priceForm: {
|
||||||
|
price: "", // 只存数字字符串
|
||||||
|
currency: "USD", // USD | RUB | AED | EUR
|
||||||
|
lang: "en" // en | ru | es | ar
|
||||||
|
},
|
||||||
|
currencyOptions: [
|
||||||
|
{ value: "USD", text: "美元" },
|
||||||
|
{ value: "CNY", text: "人民币" },
|
||||||
|
{ value: "RUB", text: "卢布" },
|
||||||
|
{ value: "AED", text: "迪拉姆" },
|
||||||
|
{ value: "EUR", text: "欧元" }
|
||||||
|
],
|
||||||
|
langOptions: [
|
||||||
|
{ text: "英语", value: "en" },
|
||||||
|
{ text: "俄语", value: "ru" },
|
||||||
|
{ text: "西班牙语", value: "es" },
|
||||||
|
{ text: "阿拉伯语", value: "ar" }
|
||||||
|
],
|
||||||
|
tradeTermOptions: [
|
||||||
|
{ value: "FOB", text: "FOB" },
|
||||||
|
{ value: "CIF", text: "CIF" },
|
||||||
|
{ value: "EXW", text: "EXW" },
|
||||||
|
{ value: "DDP", text: "DDP" },
|
||||||
|
{ value: "CIP", text: "CIP" },
|
||||||
|
{ value: "FCA", text: "FCA" },
|
||||||
|
{ value: "CFR", text: "CFR" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
images() {
|
||||||
|
// 兼容:images 可能是数组、逗号字符串、或后端不同字段
|
||||||
|
const raw =
|
||||||
|
this.detail.images_pull ||[]
|
||||||
|
|
||||||
|
if (Array.isArray(raw)) {
|
||||||
|
return raw.filter(Boolean)
|
||||||
|
}
|
||||||
|
if (typeof raw === 'string') {
|
||||||
|
return raw
|
||||||
|
.split(',')
|
||||||
|
.map(s => (s || '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(options) {
|
||||||
|
// 1) 支持通过 id 打开:/pages/index/detils?id=123
|
||||||
|
this.id = options?.id || ''
|
||||||
|
// 2) 分享链接里会带 appid,用于未登录时拉起飞书免登
|
||||||
|
const appid = options?.appid || uni.getStorageSync('fsappid') || ''
|
||||||
|
if (appid) uni.setStorageSync('fsappid', appid)
|
||||||
|
// 3) 如果未登录:先去登录页,登录成功后再回到当前详情页
|
||||||
|
const token = uni.getStorageSync('token')
|
||||||
|
if (!token) {
|
||||||
|
const redirect = `/pages/index/detils?id=${this.id}${appid ? `&appid=${encodeURIComponent(appid)}` : ''}`
|
||||||
|
uni.setStorageSync('post_login_redirect', redirect)
|
||||||
|
// 使用 reLaunch,避免用户打开分享链接后历史栈混乱
|
||||||
|
uni.reLaunch({
|
||||||
|
url: `/pages/login/index?appid=${encodeURIComponent(appid)}&redirect=${encodeURIComponent(redirect)}`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.getshows()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//获取详情
|
||||||
|
getshows(){
|
||||||
|
|
||||||
|
let that = this;
|
||||||
|
request({
|
||||||
|
url:'common/usedcar/show',
|
||||||
|
method:'GET',
|
||||||
|
data:{
|
||||||
|
id:that.id
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.detail = res.data.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
goBack() {
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: 1,
|
||||||
|
fail: () => {
|
||||||
|
// 某些环境下没有历史栈,兜底回首页
|
||||||
|
uni.reLaunch({ url: '/pages/index/index' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
previewImages(startIndex) {
|
||||||
|
if (!this.images || this.images.length === 0) return
|
||||||
|
this.currentImageIndex = startIndex || 0
|
||||||
|
uni.previewImage({
|
||||||
|
current: this.images[this.currentImageIndex],
|
||||||
|
urls: this.images
|
||||||
|
})
|
||||||
|
},
|
||||||
|
downloadByAnchor(url, filename) {
|
||||||
|
try {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename || ''
|
||||||
|
a.target = '_blank'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
} catch (e) {
|
||||||
|
// 兜底:直接打开
|
||||||
|
if (typeof window !== 'undefined') window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reviewFile(file){
|
||||||
|
this.downloadByAnchor(file.src_pull, file.name)
|
||||||
|
},
|
||||||
|
// 打开弹框时调用:可传默认值(可选)
|
||||||
|
openPriceDialog() {
|
||||||
|
this.priceForm = {
|
||||||
|
trade_term:'',
|
||||||
|
price: "",
|
||||||
|
currency: "USD",
|
||||||
|
lang: "en"
|
||||||
|
}
|
||||||
|
this.$refs.inputDialog.open()
|
||||||
|
},
|
||||||
|
|
||||||
|
closePriceDialog() {
|
||||||
|
this.$refs.inputDialog.close()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 只允许数字 + 可选1个小数点(你要“纯整数”也行,我后面给你一行改法)
|
||||||
|
onPriceInput(e) {
|
||||||
|
let v = (e.detail && e.detail.value) ? String(e.detail.value) : String(this.priceForm.price || "")
|
||||||
|
|
||||||
|
// 过滤掉非数字和点
|
||||||
|
v = v.replace(/[^\d.]/g, "")
|
||||||
|
|
||||||
|
// 只保留第一个小数点
|
||||||
|
const parts = v.split(".")
|
||||||
|
if (parts.length > 2) {
|
||||||
|
v = parts[0] + "." + parts.slice(1).join("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去掉开头多余 0(保留 0.xxx)
|
||||||
|
v = v.replace(/^0+(\d)/, "$1")
|
||||||
|
if (v.startsWith(".")) v = "0" + v
|
||||||
|
|
||||||
|
this.priceForm.price = v
|
||||||
|
},
|
||||||
|
|
||||||
|
onCurrencyPickerChange(e) {
|
||||||
|
const idx = Number(e.detail.value || 0)
|
||||||
|
this.currencyIndex = idx
|
||||||
|
this.priceForm.currency = this.currencyOptions[idx]?.value || "USD"
|
||||||
|
},
|
||||||
|
|
||||||
|
onLangChange(e) {
|
||||||
|
this.priceForm.lang = e.detail.value
|
||||||
|
},
|
||||||
|
|
||||||
|
confirmPriceDialog() {
|
||||||
|
// 校验
|
||||||
|
if (!this.priceForm.trade_term) {
|
||||||
|
return uni.showToast({ title: "请选择贸易条款", icon: "none" })
|
||||||
|
}
|
||||||
|
if (!this.priceForm.price) {
|
||||||
|
return uni.showToast({ title: "请输入价格", icon: "none" })
|
||||||
|
}
|
||||||
|
const payload = {
|
||||||
|
trade_term:this.priceForm.trade_term,
|
||||||
|
price: this.priceForm.price, // 数字字符串
|
||||||
|
currency: this.priceForm.currency, // USD/RUB/AED/EUR
|
||||||
|
lang: this.priceForm.lang // en/ru/es/ar
|
||||||
|
}
|
||||||
|
console.log(payload)
|
||||||
|
this.closePriceDialog()
|
||||||
|
this.dialogInputConfirm(payload)
|
||||||
|
},
|
||||||
|
dialogInputConfirm(val) {
|
||||||
|
if (!val.price) {
|
||||||
|
uni.showToast({ title: '请输入价格', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/produce/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: this.id, price:val.price,currency:val.currency,lang:val.lang,trade_term:val.trade_term }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadpdf(this.id)
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.data.msg || '生成失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// H5 下载:用 a 标签触发
|
||||||
|
downloadByAnchor(url, filename) {
|
||||||
|
try {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename || ''
|
||||||
|
a.target = '_blank'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
} catch (e) {
|
||||||
|
// 兜底:直接打开
|
||||||
|
if (typeof window !== 'undefined') window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
downloadpdf(item) {
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadByAnchor(res.data.data.pdf_url, res.data.data.file_name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.tradeTerm{
|
||||||
|
border: 1px solid #eae9e9;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.heard{
|
||||||
|
padding: 5px 0px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f6f7fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 18rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
background: #fff;
|
||||||
|
padding: 18rpx 18rpx;
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10rpx;
|
||||||
|
padding: 10rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-img {
|
||||||
|
width: calc((100% - 20rpx) / 3);
|
||||||
|
height: 220rpx;
|
||||||
|
border-radius: 14rpx;
|
||||||
|
background: #f3f4f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-img-single {
|
||||||
|
width: 100%;
|
||||||
|
height: 420rpx;
|
||||||
|
border-radius: 14rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-badges {
|
||||||
|
position: absolute;
|
||||||
|
left: 14rpx;
|
||||||
|
bottom: 14rpx;
|
||||||
|
display: flex;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
padding: 10rpx 14rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(255, 151, 47, 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-ghost {
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin-top: 16rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
padding: 18rpx 18rpx;
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.05);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-row {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12rpx;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-item {
|
||||||
|
padding: 16rpx 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1rpx solid #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.k {
|
||||||
|
width: 180rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #374151;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #111827;
|
||||||
|
text-align: right;
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ellipsis {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
margin-left: 12rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #ff972f;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #374151;
|
||||||
|
line-height: 1.7;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding: 28rpx 0 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 14rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry {
|
||||||
|
padding: 14rpx 26rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: rgba(255, 151, 47, 0.12);
|
||||||
|
color: #ff972f;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
.fujian{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border: 1px solid #ebebeb;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.noneview{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.price-dialog{
|
||||||
|
width: 640rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-title{
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row-col{
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-label{
|
||||||
|
width: 120rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input{
|
||||||
|
flex:1;
|
||||||
|
height: 66rpx;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.pd-input-suffix-wrap{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-with-suffix{
|
||||||
|
padding-right: 180rpx; /* 给右侧币种留空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-currency-suffix{
|
||||||
|
position: absolute;
|
||||||
|
right: 14rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 140rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
::v-deep .uni-select{
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.pd-radio-group{
|
||||||
|
display:flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx 22rpx;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio-text{
|
||||||
|
margin-left: 10rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-actions{
|
||||||
|
display:flex;
|
||||||
|
gap: 18rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-btn{
|
||||||
|
flex:1;
|
||||||
|
height: 84rpx;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-cancel{
|
||||||
|
background:#f5f5f5;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-confirm{
|
||||||
|
background:#3F435B; /* 你喜欢绿色风格 */
|
||||||
|
color:#fff;
|
||||||
|
font-weight:600;
|
||||||
|
}
|
||||||
|
.pd-price-line{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-price{
|
||||||
|
flex: 1;
|
||||||
|
min-width: 240rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,839 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<view class="content">
|
||||||
|
<!-- 基础信息卡片 -->
|
||||||
|
<view class="card pro-card">
|
||||||
|
<view class="heard">
|
||||||
|
<view class="">
|
||||||
|
编号:{{detail.code?detail.code:'~'}}
|
||||||
|
</view>
|
||||||
|
<!-- <view class="pro-mark">
|
||||||
|
<text class="pro-mark-text">专业发布</text>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<u-icon @click="openPriceDialog()" name="download" size="25" />
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
<view class="title-row">
|
||||||
|
<text class="name">{{ detail.product_name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="kv">
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">车价(¥)</text>
|
||||||
|
<text class="v">{{ detail.price }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">车源地</text>
|
||||||
|
<text class="v">{{ detail.source_place}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">上牌时间</text>
|
||||||
|
<text class="v">{{ detail.plate_time }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">排量</text>
|
||||||
|
<text class="v">{{ detail.displacement }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">里程</text>
|
||||||
|
<text class="v">{{ detail.mileage }}<text v-if="detail.mileage">Km</text></text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">马力</text>
|
||||||
|
<text class="v">{{ detail.power }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">车身颜色</text>
|
||||||
|
<text class="v">{{ detail.body_color }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="kv-item">
|
||||||
|
<text class="k">创建时间</text>
|
||||||
|
<text class="v">{{ detail.created_at }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 车况介绍 -->
|
||||||
|
<view class="card">
|
||||||
|
<view class="section-title">车况介绍</view>
|
||||||
|
<text class="desc" v-if="detail.condition_desc!=''">{{ detail.condition_desc }}</text>
|
||||||
|
<view class="noneview" v-else>
|
||||||
|
<img src="/static/image/none.png" alt="">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 视频区域(专业发布特有) -->
|
||||||
|
<view class="card video-card" v-if="videoList.length > 0">
|
||||||
|
<view class="section-title">
|
||||||
|
<u-icon name="video" size="18" color="#2E6CF6"></u-icon>
|
||||||
|
<text class="title-text">产品视频</text>
|
||||||
|
<text class="video-count">({{ videoList.length }}个)</text>
|
||||||
|
</view>
|
||||||
|
<view class="video-grid">
|
||||||
|
<view
|
||||||
|
class="video-item"
|
||||||
|
v-for="(video, index) in videoList"
|
||||||
|
:key="index"
|
||||||
|
@click="playVideo(video)"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
class="video-player"
|
||||||
|
:src="video"
|
||||||
|
:poster="video + '?vframe/jpg/offset/1'"
|
||||||
|
controls
|
||||||
|
show-center-play-btn
|
||||||
|
object-fit="cover"
|
||||||
|
></video>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- FAQ 问答区域(专业发布特有) -->
|
||||||
|
<view class="card faq-card" v-if="faqList.length > 0">
|
||||||
|
<view class="section-title">
|
||||||
|
<u-icon name="question-circle" size="18" color="#FF972F"></u-icon>
|
||||||
|
<text class="title-text">常见问题 FAQ</text>
|
||||||
|
<text class="faq-count">({{ faqList.length }}组)</text>
|
||||||
|
</view>
|
||||||
|
<view class="faq-list">
|
||||||
|
<view class="faq-item" v-for="(faq, index) in faqList" :key="index">
|
||||||
|
<view class="faq-question">
|
||||||
|
<text class="faq-label">问:</text>
|
||||||
|
<text class="faq-text">{{ faq.question }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="faq-answer">
|
||||||
|
<text class="faq-label">答:</text>
|
||||||
|
<text class="faq-text">{{ faq.answer }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 产品图 -->
|
||||||
|
<view class="hero">
|
||||||
|
<view class="section-title">产品图</view>
|
||||||
|
<view class="img-grid">
|
||||||
|
<image
|
||||||
|
v-for="(src, i) in detail.images_pull"
|
||||||
|
:key="i"
|
||||||
|
class="grid-img"
|
||||||
|
:src="src"
|
||||||
|
mode="aspectFill"
|
||||||
|
@click="previewImages(i)"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 附件 -->
|
||||||
|
<view class="hero">
|
||||||
|
<view class="section-title">附件</view>
|
||||||
|
<view v-if="detail.attachment_pull.length>0">
|
||||||
|
<view v-for="(file, i) in detail.attachment_pull" :key="i" class="fujian" @click="reviewFile(file)">
|
||||||
|
<p>{{file.name}}</p>
|
||||||
|
<view>查看</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="noneview" v-else>
|
||||||
|
<img src="/static/image/none.png" alt="">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 价格设置弹框 -->
|
||||||
|
<uni-popup ref="inputDialog" type="dialog">
|
||||||
|
<view class="price-dialog">
|
||||||
|
<view class="pd-title">设置价格</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">贸易条款</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<uni-data-select
|
||||||
|
v-model="priceForm.trade_term"
|
||||||
|
class="tradeTerm"
|
||||||
|
:localdata="tradeTermOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">价格</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<view class="pd-input-suffix-wrap">
|
||||||
|
<input
|
||||||
|
class="pd-input pd-input-price pd-input-with-suffix"
|
||||||
|
v-model="priceForm.price"
|
||||||
|
type="number"
|
||||||
|
inputmode="decimal"
|
||||||
|
placeholder="请输入数字"
|
||||||
|
@input="onPriceInput"
|
||||||
|
/>
|
||||||
|
<view class="pd-currency-suffix">
|
||||||
|
<uni-data-select
|
||||||
|
v-model="priceForm.currency"
|
||||||
|
:localdata="currencyOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 语言单选 -->
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">语言</view>
|
||||||
|
<radio-group class="pd-radio-group" @change="onLangChange">
|
||||||
|
<label class="pd-radio" v-for="l in langOptions" :key="l.value">
|
||||||
|
<radio :value="l.value" :checked="priceForm.lang === l.value" />
|
||||||
|
<text class="pd-radio-text">{{ l.text }}</text>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<view class="pd-actions">
|
||||||
|
<view class="pd-btn pd-cancel" @tap="closePriceDialog">取消</view>
|
||||||
|
<view class="pd-btn pd-confirm" @tap="confirmPriceDialog">确认</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
<!-- 视频播放弹窗 -->
|
||||||
|
<uni-popup ref="videoPopup" type="center">
|
||||||
|
<view class="video-popup">
|
||||||
|
<view class="video-popup-close" @click="closeVideoPopup">
|
||||||
|
<u-icon name="close" size="24" color="#fff"></u-icon>
|
||||||
|
</view>
|
||||||
|
<video
|
||||||
|
class="popup-video-player"
|
||||||
|
:src="currentVideoUrl"
|
||||||
|
controls
|
||||||
|
autoplay
|
||||||
|
object-fit="contain"
|
||||||
|
></video>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request, showToast } from '@/api/apiT.js'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
id: '',
|
||||||
|
appid: '',
|
||||||
|
detail: {},
|
||||||
|
currentImageIndex: 0,
|
||||||
|
currentVideoUrl: '',
|
||||||
|
priceForm: {
|
||||||
|
price: "",
|
||||||
|
currency: "USD",
|
||||||
|
lang: "en"
|
||||||
|
},
|
||||||
|
currencyOptions: [
|
||||||
|
{ value: "USD", text: "美元" },
|
||||||
|
{ value: "CNY", text: "人民币" },
|
||||||
|
{ value: "RUB", text: "卢布" },
|
||||||
|
{ value: "AED", text: "迪拉姆" },
|
||||||
|
{ value: "EUR", text: "欧元" }
|
||||||
|
],
|
||||||
|
langOptions: [
|
||||||
|
{ text: "英语", value: "en" },
|
||||||
|
{ text: "俄语", value: "ru" },
|
||||||
|
{ text: "西班牙语", value: "es" },
|
||||||
|
{ text: "阿拉伯语", value: "ar" }
|
||||||
|
],
|
||||||
|
tradeTermOptions: [
|
||||||
|
{ value: "FOB", text: "FOB" },
|
||||||
|
{ value: "CIF", text: "CIF" },
|
||||||
|
{ value: "EXW", text: "EXW" },
|
||||||
|
{ value: "DDP", text: "DDP" },
|
||||||
|
{ value: "CIP", text: "CIP" },
|
||||||
|
{ value: "FCA", text: "FCA" },
|
||||||
|
{ value: "CFR", text: "CFR" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 处理图片列表
|
||||||
|
images() {
|
||||||
|
const raw = this.detail.images_pull || []
|
||||||
|
if (Array.isArray(raw)) {
|
||||||
|
return raw.filter(Boolean)
|
||||||
|
}
|
||||||
|
if (typeof raw === 'string') {
|
||||||
|
return raw.split(',').map(s => (s || '').trim()).filter(Boolean)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
// 处理视频列表
|
||||||
|
videoList() {
|
||||||
|
// 优先使用 video_pull(完整URL)
|
||||||
|
if (Array.isArray(this.detail.video_pull) && this.detail.video_pull.length) {
|
||||||
|
return this.detail.video_pull.filter(Boolean)
|
||||||
|
}
|
||||||
|
// 兼容 intro_video 字段
|
||||||
|
if (!this.detail.intro_video) return []
|
||||||
|
if (Array.isArray(this.detail.intro_video)) {
|
||||||
|
return this.detail.intro_video.filter(Boolean)
|
||||||
|
}
|
||||||
|
if (typeof this.detail.intro_video === 'string') {
|
||||||
|
return this.detail.intro_video.split(',').map(s => (s || '').trim()).filter(Boolean)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
// 处理FAQ列表
|
||||||
|
faqList() {
|
||||||
|
if (!this.detail.faqs) return []
|
||||||
|
if (Array.isArray(this.detail.faqs)) {
|
||||||
|
return this.detail.faqs.filter(f => f.question && f.answer)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(options) {
|
||||||
|
this.id = options?.id || ''
|
||||||
|
const appid = options?.appid || uni.getStorageSync('fsappid') || ''
|
||||||
|
if (appid) uni.setStorageSync('fsappid', appid)
|
||||||
|
|
||||||
|
// 登录检查
|
||||||
|
const token = uni.getStorageSync('token')
|
||||||
|
if (!token) {
|
||||||
|
const redirect = `/pages/index/detilsPro?id=${this.id}${appid ? `&appid=${encodeURIComponent(appid)}` : ''}`
|
||||||
|
uni.setStorageSync('post_login_redirect', redirect)
|
||||||
|
uni.reLaunch({
|
||||||
|
url: `/pages/login/index?appid=${encodeURIComponent(appid)}&redirect=${encodeURIComponent(redirect)}`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.getshows()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取专业发布详情
|
||||||
|
getshows() {
|
||||||
|
const that = this
|
||||||
|
request({
|
||||||
|
url: 'common/usedcardetail/show',
|
||||||
|
method: 'GET',
|
||||||
|
data: { id: that.id }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.detail = res.data.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 预览图片
|
||||||
|
previewImages(startIndex) {
|
||||||
|
if (!this.images || this.images.length === 0) return
|
||||||
|
this.currentImageIndex = startIndex || 0
|
||||||
|
uni.previewImage({
|
||||||
|
current: this.images[this.currentImageIndex],
|
||||||
|
urls: this.images
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 播放视频
|
||||||
|
playVideo(videoUrl) {
|
||||||
|
this.currentVideoUrl = videoUrl
|
||||||
|
this.$refs.videoPopup.open()
|
||||||
|
},
|
||||||
|
// 关闭视频弹窗
|
||||||
|
closeVideoPopup() {
|
||||||
|
this.$refs.videoPopup.close()
|
||||||
|
this.currentVideoUrl = ''
|
||||||
|
},
|
||||||
|
// 下载文件
|
||||||
|
downloadByAnchor(url, filename) {
|
||||||
|
try {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename || ''
|
||||||
|
a.target = '_blank'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof window !== 'undefined') window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 查看附件
|
||||||
|
reviewFile(file) {
|
||||||
|
this.downloadByAnchor(file.src_pull, file.name)
|
||||||
|
},
|
||||||
|
// 打开价格弹框
|
||||||
|
openPriceDialog() {
|
||||||
|
this.priceForm = {
|
||||||
|
trade_term: '',
|
||||||
|
price: "",
|
||||||
|
currency: "USD",
|
||||||
|
lang: "en"
|
||||||
|
}
|
||||||
|
this.$refs.inputDialog.open()
|
||||||
|
},
|
||||||
|
// 关闭价格弹框
|
||||||
|
closePriceDialog() {
|
||||||
|
this.$refs.inputDialog.close()
|
||||||
|
},
|
||||||
|
// 价格输入处理
|
||||||
|
onPriceInput(e) {
|
||||||
|
let v = (e.detail && e.detail.value) ? String(e.detail.value) : String(this.priceForm.price || "")
|
||||||
|
v = v.replace(/[^\d.]/g, "")
|
||||||
|
const parts = v.split(".")
|
||||||
|
if (parts.length > 2) {
|
||||||
|
v = parts[0] + "." + parts.slice(1).join("")
|
||||||
|
}
|
||||||
|
v = v.replace(/^0+(\d)/, "$1")
|
||||||
|
if (v.startsWith(".")) v = "0" + v
|
||||||
|
this.priceForm.price = v
|
||||||
|
},
|
||||||
|
// 语言切换
|
||||||
|
onLangChange(e) {
|
||||||
|
this.priceForm.lang = e.detail.value
|
||||||
|
},
|
||||||
|
// 确认价格弹框
|
||||||
|
confirmPriceDialog() {
|
||||||
|
if (!this.priceForm.trade_term) {
|
||||||
|
return uni.showToast({ title: "请选择贸易条款", icon: "none" })
|
||||||
|
}
|
||||||
|
if (!this.priceForm.price) {
|
||||||
|
return uni.showToast({ title: "请输入价格", icon: "none" })
|
||||||
|
}
|
||||||
|
const payload = {
|
||||||
|
trade_term: this.priceForm.trade_term,
|
||||||
|
price: this.priceForm.price,
|
||||||
|
currency: this.priceForm.currency,
|
||||||
|
lang: this.priceForm.lang
|
||||||
|
}
|
||||||
|
this.closePriceDialog()
|
||||||
|
this.dialogInputConfirm(payload)
|
||||||
|
},
|
||||||
|
// 生成PDF
|
||||||
|
dialogInputConfirm(val) {
|
||||||
|
if (!val.price) {
|
||||||
|
uni.showToast({ title: '请输入价格', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url: 'common/usedcardetail/produce/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: {
|
||||||
|
id: this.id,
|
||||||
|
price: val.price,
|
||||||
|
currency: val.currency,
|
||||||
|
lang: val.lang,
|
||||||
|
trade_term: val.trade_term
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadpdf(this.id)
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.data.msg || '生成失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 下载PDF
|
||||||
|
downloadpdf(item) {
|
||||||
|
request({
|
||||||
|
url: 'common/usedcardetail/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadByAnchor(res.data.data.pdf_url, res.data.data.file_name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f6f7fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 18rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 专业发布卡片样式
|
||||||
|
.pro-card {
|
||||||
|
background: linear-gradient(135deg, #fff 0%, #f8f9ff 100%);
|
||||||
|
border: 1px solid rgba(46, 108, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heard {
|
||||||
|
padding: 5px 0px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 专业发布标记
|
||||||
|
.pro-mark {
|
||||||
|
padding: 4rpx 12rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: linear-gradient(135deg, #2E6CF6 0%, #1a5dd9 100%);
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(46, 108, 246, 0.3);
|
||||||
|
|
||||||
|
.pro-mark-text {
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin-top: 16rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
padding: 18rpx 18rpx;
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.05);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 视频卡片样式
|
||||||
|
.video-card {
|
||||||
|
border: 1px solid rgba(46, 108, 246, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FAQ卡片样式
|
||||||
|
.faq-card {
|
||||||
|
border: 1px solid rgba(255, 151, 47, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-item {
|
||||||
|
padding: 16rpx 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1rpx solid #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.k {
|
||||||
|
width: 180rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #374151;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #111827;
|
||||||
|
text-align: right;
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-count,
|
||||||
|
.faq-count {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #999;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #374151;
|
||||||
|
line-height: 1.7;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
background: #fff;
|
||||||
|
padding: 18rpx 18rpx;
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10rpx;
|
||||||
|
padding: 10rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-img {
|
||||||
|
width: calc((100% - 20rpx) / 3);
|
||||||
|
height: 220rpx;
|
||||||
|
border-radius: 14rpx;
|
||||||
|
background: #f3f4f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 视频网格样式
|
||||||
|
.video-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-item {
|
||||||
|
width: calc((100% - 16rpx) / 2);
|
||||||
|
height: 240rpx;
|
||||||
|
border-radius: 14rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-player {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FAQ列表样式
|
||||||
|
.faq-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item {
|
||||||
|
padding: 16rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background: linear-gradient(135deg, rgba(255, 151, 47, 0.05) 0%, rgba(255, 151, 47, 0.02) 100%);
|
||||||
|
border: 1px solid rgba(255, 151, 47, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-question,
|
||||||
|
.faq-answer {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #FF972F;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-text {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #374151;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fujian {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border: 1px solid #ebebeb;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noneview {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 价格弹框样式
|
||||||
|
.tradeTerm {
|
||||||
|
border: 1px solid #eae9e9;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-dialog {
|
||||||
|
width: 640rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-title {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-label {
|
||||||
|
width: 120rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input {
|
||||||
|
flex: 1;
|
||||||
|
height: 66rpx;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-suffix-wrap {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-with-suffix {
|
||||||
|
padding-right: 180rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-currency-suffix {
|
||||||
|
position: absolute;
|
||||||
|
right: 14rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 140rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .uni-select {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx 22rpx;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio-text {
|
||||||
|
margin-left: 10rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 18rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 84rpx;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-cancel {
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-confirm {
|
||||||
|
background: #3F435B;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-price-line {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-price {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 240rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 视频弹窗样式
|
||||||
|
.video-popup {
|
||||||
|
position: relative;
|
||||||
|
width: 680rpx;
|
||||||
|
height: 480rpx;
|
||||||
|
background: #000;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-popup-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 20rpx;
|
||||||
|
right: 20rpx;
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-video-player {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,617 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<z-paging ref="paging" v-model="list" @query="queryList" empty-view-text="暂无数据!">
|
||||||
|
<!-- <uni-nav-bar leftText=" " :fixed="true" :border="false" color="#fff" backgroundColor="#3F435B" :statusBar="true" title="首页"></uni-nav-bar> -->
|
||||||
|
<!-- 顶部:标题 + 搜索(不想要搜索可直接删除这一块) -->
|
||||||
|
<view class="page-head">
|
||||||
|
<view class="head-search">
|
||||||
|
<u-search
|
||||||
|
v-model="keyword"
|
||||||
|
placeholder="请输入关键词"
|
||||||
|
:show-action="false"
|
||||||
|
shape="round"
|
||||||
|
@change="onKeywordChange"
|
||||||
|
@search="onSearch"
|
||||||
|
@clear="onSearch"
|
||||||
|
/>
|
||||||
|
<view class="statussearch" @click="show=true">
|
||||||
|
<text class="year-text">{{status_name || '状态'}}</text>
|
||||||
|
<u-icon name="arrow-down" size="14" color="#999"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-picker :show="show" :columns="columns" keyName="label" @confirm="onstatus" @cancel="show = false"></u-picker>
|
||||||
|
</view>
|
||||||
|
<view class="list-wrap">
|
||||||
|
<CarCard
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.id"
|
||||||
|
:item="item"
|
||||||
|
@pdfchange="onSearch"
|
||||||
|
@request-price="onRequestPrice"
|
||||||
|
@restchange="onSearch"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
<!-- <uni-popup ref="inputDialog" type="dialog">
|
||||||
|
<uni-popup-dialog
|
||||||
|
mode="input"
|
||||||
|
title="请输入价格"
|
||||||
|
:value="priceDialogValue"
|
||||||
|
placeholder="请输入车辆价格"
|
||||||
|
@confirm="dialogInputConfirm"
|
||||||
|
/>
|
||||||
|
</uni-popup> -->
|
||||||
|
<uni-popup ref="inputDialog" type="dialog">
|
||||||
|
<view class="price-dialog">
|
||||||
|
<view class="pd-title">设置价格</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">贸易条款</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<uni-data-select
|
||||||
|
v-model="priceForm.trade_term"
|
||||||
|
class="tradeTerm"
|
||||||
|
:localdata="tradeTermOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">价格</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<view class="pd-input-suffix-wrap">
|
||||||
|
<input
|
||||||
|
class="pd-input pd-input-price pd-input-with-suffix"
|
||||||
|
v-model="priceForm.price"
|
||||||
|
type="number"
|
||||||
|
inputmode="decimal"
|
||||||
|
placeholder="请输入数字"
|
||||||
|
@input="onPriceInput"
|
||||||
|
/>
|
||||||
|
<!-- 币种下拉:放在输入框内部右侧(无边框) -->
|
||||||
|
<view class="pd-currency-suffix">
|
||||||
|
<uni-data-select
|
||||||
|
class="pd-currency-select-suffix"
|
||||||
|
v-model="priceForm.currency"
|
||||||
|
:localdata="currencyOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 语言单选 -->
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">语言</view>
|
||||||
|
<radio-group class="pd-radio-group" @change="onLangChange">
|
||||||
|
<label class="pd-radio" v-for="l in langOptions" :key="l.value">
|
||||||
|
<radio :value="l.value" :checked="priceForm.lang === l.value" />
|
||||||
|
<text class="pd-radio-text">{{ l.text }}</text>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<view class="pd-actions">
|
||||||
|
<view class="pd-btn pd-cancel" @tap="closePriceDialog">取消</view>
|
||||||
|
<view class="pd-btn pd-confirm" @tap="confirmPriceDialog">确认</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<CustomTabBar class="h5-custom-tabbar" />
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
import CarCard from '@/components/CarCard/CarCard.vue'
|
||||||
|
import CustomTabBar from '@/custom-tab-bar/index.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CarCard,
|
||||||
|
CustomTabBar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
status_id:1,
|
||||||
|
status_name:'',
|
||||||
|
columns: [
|
||||||
|
[{
|
||||||
|
label: '正常',
|
||||||
|
id: 1
|
||||||
|
}, {
|
||||||
|
label: '已售出',
|
||||||
|
id: 2
|
||||||
|
}, {
|
||||||
|
label: '已归档',
|
||||||
|
id: 3
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
priceDialogItem: null,
|
||||||
|
priceDialogIndex: -1,
|
||||||
|
priceDialogValue: '',
|
||||||
|
keyword: '',
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
loading: false,
|
||||||
|
finished: false,
|
||||||
|
list: [],
|
||||||
|
priceForm: {
|
||||||
|
trade_term:'',
|
||||||
|
price: "", // 只存数字字符串
|
||||||
|
currency: "USD", // USD | RUB | AED | EUR
|
||||||
|
lang: "en" // en | ru | es | ar
|
||||||
|
},
|
||||||
|
currencyOptions: [
|
||||||
|
{ value: "USD", text: "美元" },
|
||||||
|
{ value: "CNY", text: "人民币" },
|
||||||
|
{ value: "RUB", text: "卢布" },
|
||||||
|
{ value: "AED", text: "迪拉姆" },
|
||||||
|
{ value: "EUR", text: "欧元" }
|
||||||
|
],
|
||||||
|
langOptions: [
|
||||||
|
{ text: "英语", value: "en" },
|
||||||
|
{ text: "俄语", value: "ru" },
|
||||||
|
{ text: "西班牙语", value: "es" },
|
||||||
|
{ text: "阿拉伯语", value: "ar" }
|
||||||
|
],
|
||||||
|
tradeTermOptions: [
|
||||||
|
{ value: "FOB", text: "FOB" },
|
||||||
|
{ value: "CIF", text: "CIF" },
|
||||||
|
{ value: "EXW", text: "EXW" },
|
||||||
|
{ value: "DDP", text: "DDP" },
|
||||||
|
{ value: "CIP", text: "CIP" },
|
||||||
|
{ value: "FCA", text: "FCA" },
|
||||||
|
{ value: "CFR", text: "CFR" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.initFeishuShare()
|
||||||
|
// H5:处理分享兜底参数 r(如果路由没命中/经历登录回跳,会先落到首页)
|
||||||
|
// #ifdef H5
|
||||||
|
try {
|
||||||
|
const u = new URL(window.location.href)
|
||||||
|
const r = u.searchParams.get('r')
|
||||||
|
if (r) {
|
||||||
|
const target = decodeURIComponent(r)
|
||||||
|
// 清理地址栏的 r,避免反复跳转
|
||||||
|
u.searchParams.delete('r')
|
||||||
|
window.history.replaceState({}, '', u.toString())
|
||||||
|
// 让首页加载完再跳
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateTo({ url: target })
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isFeishuEnv() {
|
||||||
|
// 飞书/ Lark 客户端内置浏览器 UA 通常包含 Feishu / Lark
|
||||||
|
try {
|
||||||
|
const ua = (navigator.userAgent || '').toLowerCase()
|
||||||
|
return ua.includes('feishu') || ua.includes('lark')
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadFeishuJSSDK() {
|
||||||
|
// 动态加载飞书 H5 JS-SDK(避免你还要改 public/index.html)
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
// 已加载
|
||||||
|
if (typeof window !== 'undefined' && window.h5sdk && window.tt) return resolve(true)
|
||||||
|
// H5 才有 document
|
||||||
|
if (typeof document === 'undefined') return reject(new Error('not in h5 environment'))
|
||||||
|
// 已插入但未 ready
|
||||||
|
const existed = document.querySelector('script[data-feishu-h5sdk="1"]')
|
||||||
|
if (existed) {
|
||||||
|
existed.addEventListener('load', () => resolve(true))
|
||||||
|
existed.addEventListener('error', () => reject(new Error('feishu sdk load error')))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const s = document.createElement('script')
|
||||||
|
s.async = true
|
||||||
|
s.src = 'https://lf-scm-cn.feishucdn.com/lark/op/h5-js-sdk-1.5.44.js'
|
||||||
|
s.onload = () => resolve(true)
|
||||||
|
s.onerror = () => reject(new Error('feishu sdk load error'))
|
||||||
|
document.head.appendChild(s)
|
||||||
|
} catch (e) {
|
||||||
|
reject(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getFeishuSignUrl() {
|
||||||
|
// 飞书签名通常要求“去掉 hash 的完整 URL”
|
||||||
|
try {
|
||||||
|
return window.location.href.split('#')[0]
|
||||||
|
} catch (e) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initFeishuShare() {
|
||||||
|
try {
|
||||||
|
// 确保在飞书环境
|
||||||
|
// if (!this.isFeishuEnv()) return
|
||||||
|
// 动态加载 SDK
|
||||||
|
this.loadFeishuJSSDK()
|
||||||
|
|
||||||
|
// 这里需要后端提供签名接口:返回 { appId, timestamp, nonceStr, signature }
|
||||||
|
// 你可以按你后端习惯改成:request({ url: 'xxx', ... })
|
||||||
|
// const signUrl = encodeURIComponent(this.getFeishuSignUrl())
|
||||||
|
const signUrl = this.getFeishuSignUrl()
|
||||||
|
|
||||||
|
request({
|
||||||
|
url:'common/auth/feishu/signature',
|
||||||
|
method:'get',
|
||||||
|
data: {url:signUrl,app_id:uni.getStorageSync('fsappid')}
|
||||||
|
}).then(res => {
|
||||||
|
var cfg = res.data.data;
|
||||||
|
window.h5sdk.config({
|
||||||
|
appId: cfg.appId || uni.getStorageSync('fsappid'),
|
||||||
|
timestamp: cfg.timestamp,
|
||||||
|
nonceStr: cfg.nonceStr,
|
||||||
|
signature: cfg.signature,
|
||||||
|
jsApiList: ['shareWebContent','share']
|
||||||
|
})
|
||||||
|
|
||||||
|
window.h5sdk.ready(() => {
|
||||||
|
this._feishuReady = true
|
||||||
|
})
|
||||||
|
window.h5sdk.error((err) => {
|
||||||
|
this._feishuReady = false
|
||||||
|
console.error('Feishu JSSDK error:', err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
// 不要阻塞页面,失败就走 H5 的兜底分享
|
||||||
|
console.error('initFeishuShare failed:', e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequestPrice(payload) {
|
||||||
|
// payload: { item, index }
|
||||||
|
this.priceDialogItem = payload && payload.item ? payload.item : null
|
||||||
|
this.priceDialogIndex = payload && typeof payload.index === 'number' ? payload.index : -1
|
||||||
|
this.priceDialogValue = ''
|
||||||
|
this.priceForm = {
|
||||||
|
trade_term:'',
|
||||||
|
price:"",
|
||||||
|
currency: "USD",
|
||||||
|
lang: "en"
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.inputDialog && this.$refs.inputDialog.open()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// H5 下载:用 a 标签触发
|
||||||
|
downloadByAnchor(url, filename) {
|
||||||
|
try {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename || ''
|
||||||
|
a.target = '_blank'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
} catch (e) {
|
||||||
|
// 兜底:直接打开
|
||||||
|
if (typeof window !== 'undefined') window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
downloadpdf(item) {
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item.id }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadByAnchor(res.data.data.pdf_url, res.data.data.file_name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closePriceDialog() {
|
||||||
|
this.$refs.inputDialog.close()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 只允许数字 + 可选1个小数点(你要“纯整数”也行,我后面给你一行改法)
|
||||||
|
onPriceInput(e) {
|
||||||
|
let v = (e.detail && e.detail.value) ? String(e.detail.value) : String(this.priceForm.price || "")
|
||||||
|
|
||||||
|
// 过滤掉非数字和点
|
||||||
|
v = v.replace(/[^\d.]/g, "")
|
||||||
|
|
||||||
|
// 只保留第一个小数点
|
||||||
|
const parts = v.split(".")
|
||||||
|
if (parts.length > 2) {
|
||||||
|
v = parts[0] + "." + parts.slice(1).join("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去掉开头多余 0(保留 0.xxx)
|
||||||
|
v = v.replace(/^0+(\d)/, "$1")
|
||||||
|
if (v.startsWith(".")) v = "0" + v
|
||||||
|
|
||||||
|
this.priceForm.price = v
|
||||||
|
},
|
||||||
|
|
||||||
|
onCurrencyPickerChange(e) {
|
||||||
|
const idx = Number(e.detail.value || 0)
|
||||||
|
this.currencyIndex = idx
|
||||||
|
this.priceForm.currency = this.currencyOptions[idx]?.value || "USD"
|
||||||
|
},
|
||||||
|
|
||||||
|
onLangChange(e) {
|
||||||
|
this.priceForm.lang = e.detail.value
|
||||||
|
},
|
||||||
|
|
||||||
|
confirmPriceDialog() {
|
||||||
|
if (!this.priceForm.trade_term) {
|
||||||
|
return uni.showToast({ title: "请选择贸易条款", icon: "none" })
|
||||||
|
}
|
||||||
|
// 校验
|
||||||
|
if (!this.priceForm.price) {
|
||||||
|
return uni.showToast({ title: "请输入价格", icon: "none" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
trade_term:this.priceForm.trade_term,
|
||||||
|
price: this.priceForm.price, // 数字字符串
|
||||||
|
currency: this.priceForm.currency, // USD/RUB/AED/EUR
|
||||||
|
lang: this.priceForm.lang // en/ru/es/ar
|
||||||
|
}
|
||||||
|
console.log(payload)
|
||||||
|
this.closePriceDialog()
|
||||||
|
this.dialogInputConfirm(payload)
|
||||||
|
},
|
||||||
|
dialogInputConfirm(val) {
|
||||||
|
const item = this.priceDialogItem
|
||||||
|
const index = this.priceDialogIndex
|
||||||
|
|
||||||
|
if (!item) return
|
||||||
|
if (!val.price) {
|
||||||
|
uni.showToast({ title: '请输入价格', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/produce/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item.id, price:val.price,currency:val.currency,lang:val.lang,trade_term:val.trade_term }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
// 通知刷新列表(你原来就是靠这个事件刷新)
|
||||||
|
this.onSearch()
|
||||||
|
|
||||||
|
this.downloadpdf(item)
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.data.msg || '生成失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onKeywordChange(val) {
|
||||||
|
// val 是输入值(uView 通常会传)
|
||||||
|
this.keyword = val
|
||||||
|
|
||||||
|
// 防抖:300ms 内持续输入只触发一次
|
||||||
|
if (this._kwTimer) clearTimeout(this._kwTimer)
|
||||||
|
this._kwTimer = setTimeout(() => {
|
||||||
|
this.onSearch()
|
||||||
|
}, 300)
|
||||||
|
},
|
||||||
|
onSearch() {
|
||||||
|
this.$refs.paging && this.$refs.paging.reload()
|
||||||
|
},
|
||||||
|
queryList(pageNo, pageSize, from) {
|
||||||
|
this.loading = true;
|
||||||
|
var that = this;
|
||||||
|
const params = {
|
||||||
|
current:pageNo,
|
||||||
|
status:this.status_id,
|
||||||
|
size:pageSize
|
||||||
|
};
|
||||||
|
params.keyword = this.keyword;
|
||||||
|
request({
|
||||||
|
url:'common/usedcar/list',
|
||||||
|
method:'get',
|
||||||
|
data: params
|
||||||
|
}).then(res => {
|
||||||
|
if(res.data.code ==200){
|
||||||
|
var datas = res.data.data.records;
|
||||||
|
this.$refs.paging.complete(datas);
|
||||||
|
}else{
|
||||||
|
}
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
//
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onstatus(e){
|
||||||
|
if (e.value && e.value[0]) {
|
||||||
|
const selectedItem = typeof e.value[0] === 'object' ? e.value[0] : { value: e.value[0], label: e.value[0].toString() };
|
||||||
|
this.status_name = selectedItem.label;
|
||||||
|
this.status_id = selectedItem.id;
|
||||||
|
this.show = false;
|
||||||
|
this.$refs.paging && this.$refs.paging.reload()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tradeTerm{
|
||||||
|
border: 1px solid #eae9e9;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f4f6f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifdef H5 */
|
||||||
|
.page {
|
||||||
|
/* 给自定义 TabBar 预留空间,避免内容被遮挡 */
|
||||||
|
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
.page-head {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 50px;
|
||||||
|
z-index: 99;
|
||||||
|
// padding: 28rpx 24rpx 18rpx;
|
||||||
|
// background: linear-gradient(180deg, rgba(255, 151, 47, 0.22) 0%, rgba(255, 151, 47, 0.06) 55%, #f4f6f8 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.head-search {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
border-radius: 9px 9px 0px 0px;
|
||||||
|
padding: 20rpx 10px;
|
||||||
|
box-shadow: 0 10rpx 28rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
.statussearch{
|
||||||
|
border: 1px solid #eae9e9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-wrap {
|
||||||
|
padding: 18rpx 24rpx 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loadmore {
|
||||||
|
padding: 18rpx 0 6rpx;
|
||||||
|
}
|
||||||
|
.price-dialog{
|
||||||
|
width: 640rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-title{
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row-col{
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-label{
|
||||||
|
width: 120rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input{
|
||||||
|
flex:1;
|
||||||
|
height: 66rpx;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.pd-input-suffix-wrap{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-with-suffix{
|
||||||
|
padding-right: 180rpx; /* 给右侧币种留空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-currency-suffix{
|
||||||
|
position: absolute;
|
||||||
|
right: 14rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 140rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
::v-deep .uni-select{
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.pd-radio-group{
|
||||||
|
display:flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx 22rpx;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio-text{
|
||||||
|
margin-left: 10rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-actions{
|
||||||
|
display:flex;
|
||||||
|
gap: 18rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-btn{
|
||||||
|
flex:1;
|
||||||
|
height: 84rpx;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-cancel{
|
||||||
|
background:#f5f5f5;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-confirm{
|
||||||
|
background:#3F435B; /* 你喜欢绿色风格 */
|
||||||
|
color:#fff;
|
||||||
|
font-weight:600;
|
||||||
|
}
|
||||||
|
.pd-price-line{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-price{
|
||||||
|
flex: 1;
|
||||||
|
min-width: 240rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<!-- 用户信息卡片 -->
|
||||||
|
<view class="user-card" @click="goToChanginfo">
|
||||||
|
<view class="user-info">
|
||||||
|
<image
|
||||||
|
class="avatar"
|
||||||
|
:src="userInfo.avatar_url || '/static/image/car.png'"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
<view class="user-details">
|
||||||
|
<text class="nickname">{{ userInfo.name || '未设置昵称' }}</text>
|
||||||
|
<text class="phone">{{ userInfo.mobile || '未绑定手机号' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 功能入口 -->
|
||||||
|
<view class="menu-section">
|
||||||
|
<view class="menu-item" @tap="goToMyPublish">
|
||||||
|
<view class="menu-icon">
|
||||||
|
<u-icon name="list" size="24" color="#3F435B"></u-icon>
|
||||||
|
</view>
|
||||||
|
<text class="menu-text">我的发布</text>
|
||||||
|
<view class="menu-arrow">
|
||||||
|
<u-icon name="arrow-right" size="18" color="#999"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
userInfo: {
|
||||||
|
avatar_url: '',
|
||||||
|
name: '',
|
||||||
|
mobile: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.getUserInfo()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
// 页面显示时刷新用户信息
|
||||||
|
this.getUserInfo()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取用户信息
|
||||||
|
getUserInfo() {
|
||||||
|
request({
|
||||||
|
url: 'user/getInfo',
|
||||||
|
method: 'get'
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 0 || res.data.code == 200) {
|
||||||
|
this.userInfo = {
|
||||||
|
avatar_url: res.data.data.avatar_url || '',
|
||||||
|
name: res.data.data.name || '',
|
||||||
|
mobile: res.data.data.mobile || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
// 获取失败时使用默认值
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 跳转到我的发布列表
|
||||||
|
goToMyPublish() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/index/myPublish'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 跳转到个人信息
|
||||||
|
goToChanginfo() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/index/changinfo'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f4f6f8;
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-card {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-radius: 18rpx;
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #eef2f7;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nickname {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-section {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-radius: 18rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 30rpx;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item:active {
|
||||||
|
background-color: #f9fafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
width: 48rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
background: #f3f4f6;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-text {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #111827;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-arrow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,615 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<!-- 列表 -->
|
||||||
|
<z-paging ref="paging" v-model="list" @query="queryList" empty-view-text="暂无数据!">
|
||||||
|
<!-- <uni-nav-bar leftText=" " :fixed="true" :border="false" color="#fff" backgroundColor="#3F435B" :statusBar="true" title="首页"></uni-nav-bar> -->
|
||||||
|
<!-- 顶部:标题 + 搜索(不想要搜索可直接删除这一块) -->
|
||||||
|
<view class="page-head">
|
||||||
|
<view class="head-search">
|
||||||
|
<u-search
|
||||||
|
v-model="keyword"
|
||||||
|
placeholder="请输入关键词"
|
||||||
|
:show-action="false"
|
||||||
|
shape="round"
|
||||||
|
@change="onKeywordChange"
|
||||||
|
@search="onSearch"
|
||||||
|
@clear="onSearch"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="list-wrap">
|
||||||
|
<uni-swipe-action-item
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.id"
|
||||||
|
:right-options="options1"
|
||||||
|
@click="swipeClick($event, item)"
|
||||||
|
>
|
||||||
|
<CarCard
|
||||||
|
:item="item"
|
||||||
|
:ismy="true"
|
||||||
|
@pdfchange="onSearch"
|
||||||
|
@request-price="onRequestPrice"
|
||||||
|
/>
|
||||||
|
</uni-swipe-action-item>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
<uni-popup ref="inputDialog" type="dialog">
|
||||||
|
<view class="price-dialog">
|
||||||
|
<view class="pd-title">设置价格</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">贸易条款</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<uni-data-select
|
||||||
|
v-model="priceForm.trade_term"
|
||||||
|
class="tradeTerm"
|
||||||
|
:localdata="tradeTermOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">价格</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<view class="pd-input-suffix-wrap">
|
||||||
|
<input
|
||||||
|
class="pd-input pd-input-price pd-input-with-suffix"
|
||||||
|
v-model="priceForm.price"
|
||||||
|
type="number"
|
||||||
|
inputmode="decimal"
|
||||||
|
placeholder="请输入数字"
|
||||||
|
@input="onPriceInput"
|
||||||
|
/>
|
||||||
|
<!-- 币种下拉:放在输入框内部右侧(无边框) -->
|
||||||
|
<view class="pd-currency-suffix">
|
||||||
|
<uni-data-select
|
||||||
|
class="pd-currency-select-suffix"
|
||||||
|
v-model="priceForm.currency"
|
||||||
|
:localdata="currencyOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 语言单选 -->
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">语言</view>
|
||||||
|
<radio-group class="pd-radio-group" @change="onLangChange">
|
||||||
|
<label class="pd-radio" v-for="l in langOptions" :key="l.value">
|
||||||
|
<radio :value="l.value" :checked="priceForm.lang === l.value" />
|
||||||
|
<text class="pd-radio-text">{{ l.text }}</text>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<view class="pd-actions">
|
||||||
|
<view class="pd-btn pd-cancel" @tap="closePriceDialog">取消</view>
|
||||||
|
<view class="pd-btn pd-confirm" @tap="confirmPriceDialog">确认</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<CustomTabBar class="h5-custom-tabbar" />
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
import CarCard from '@/components/CarCard/CarCard.vue'
|
||||||
|
import CustomTabBar from '@/custom-tab-bar/index.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CarCard,
|
||||||
|
CustomTabBar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
priceDialogItem: null,
|
||||||
|
priceDialogIndex: -1,
|
||||||
|
priceDialogValue: '',
|
||||||
|
options1: [{
|
||||||
|
text: '编辑',
|
||||||
|
style: {
|
||||||
|
backgroundColor: '#007aff'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
keyword: '',
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
loading: false,
|
||||||
|
finished: false,
|
||||||
|
list: [],
|
||||||
|
priceForm: {
|
||||||
|
trade_term:'',
|
||||||
|
price: "", // 只存数字字符串
|
||||||
|
currency: "USD", // USD | RUB | AED | EUR
|
||||||
|
lang: "en" // en | ru | es | ar
|
||||||
|
},
|
||||||
|
currencyOptions: [
|
||||||
|
{ value: "USD", text: "美元" },
|
||||||
|
{ value: "CNY", text: "人民币" },
|
||||||
|
{ value: "RUB", text: "卢布" },
|
||||||
|
{ value: "AED", text: "迪拉姆" },
|
||||||
|
{ value: "EUR", text: "欧元" }
|
||||||
|
],
|
||||||
|
langOptions: [
|
||||||
|
{ text: "英语", value: "en" },
|
||||||
|
{ text: "俄语", value: "ru" },
|
||||||
|
{ text: "西班牙语", value: "es" },
|
||||||
|
{ text: "阿拉伯语", value: "ar" }
|
||||||
|
],
|
||||||
|
tradeTermOptions: [
|
||||||
|
{ value: "FOB", text: "FOB" },
|
||||||
|
{ value: "CIF", text: "CIF" },
|
||||||
|
{ value: "EXW", text: "EXW" },
|
||||||
|
{ value: "DDP", text: "DDP" },
|
||||||
|
{ value: "CIP", text: "CIP" },
|
||||||
|
{ value: "FCA", text: "FCA" },
|
||||||
|
{ value: "CFR", text: "CFR" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.initFeishuShare()
|
||||||
|
// H5:处理分享兜底参数 r(如果路由没命中/经历登录回跳,会先落到首页)
|
||||||
|
// #ifdef H5
|
||||||
|
try {
|
||||||
|
const u = new URL(window.location.href)
|
||||||
|
const r = u.searchParams.get('r')
|
||||||
|
if (r) {
|
||||||
|
const target = decodeURIComponent(r)
|
||||||
|
// 清理地址栏的 r,避免反复跳转
|
||||||
|
u.searchParams.delete('r')
|
||||||
|
window.history.replaceState({}, '', u.toString())
|
||||||
|
// 让首页加载完再跳
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateTo({ url: target })
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isFeishuEnv() {
|
||||||
|
// 飞书/ Lark 客户端内置浏览器 UA 通常包含 Feishu / Lark
|
||||||
|
try {
|
||||||
|
const ua = (navigator.userAgent || '').toLowerCase()
|
||||||
|
return ua.includes('feishu') || ua.includes('lark')
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadFeishuJSSDK() {
|
||||||
|
// 动态加载飞书 H5 JS-SDK(避免你还要改 public/index.html)
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
// 已加载
|
||||||
|
if (typeof window !== 'undefined' && window.h5sdk && window.tt) return resolve(true)
|
||||||
|
// H5 才有 document
|
||||||
|
if (typeof document === 'undefined') return reject(new Error('not in h5 environment'))
|
||||||
|
// 已插入但未 ready
|
||||||
|
const existed = document.querySelector('script[data-feishu-h5sdk="1"]')
|
||||||
|
if (existed) {
|
||||||
|
existed.addEventListener('load', () => resolve(true))
|
||||||
|
existed.addEventListener('error', () => reject(new Error('feishu sdk load error')))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const s = document.createElement('script')
|
||||||
|
s.async = true
|
||||||
|
s.src = 'https://lf-scm-cn.feishucdn.com/lark/op/h5-js-sdk-1.5.44.js'
|
||||||
|
s.onload = () => resolve(true)
|
||||||
|
s.onerror = () => reject(new Error('feishu sdk load error'))
|
||||||
|
document.head.appendChild(s)
|
||||||
|
} catch (e) {
|
||||||
|
reject(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getFeishuSignUrl() {
|
||||||
|
// 飞书签名通常要求“去掉 hash 的完整 URL”
|
||||||
|
try {
|
||||||
|
return window.location.href.split('#')[0]
|
||||||
|
} catch (e) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initFeishuShare() {
|
||||||
|
try {
|
||||||
|
// 确保在飞书环境
|
||||||
|
// if (!this.isFeishuEnv()) return
|
||||||
|
// 动态加载 SDK
|
||||||
|
this.loadFeishuJSSDK()
|
||||||
|
|
||||||
|
// 这里需要后端提供签名接口:返回 { appId, timestamp, nonceStr, signature }
|
||||||
|
// 你可以按你后端习惯改成:request({ url: 'xxx', ... })
|
||||||
|
// const signUrl = encodeURIComponent(this.getFeishuSignUrl())
|
||||||
|
const signUrl = this.getFeishuSignUrl()
|
||||||
|
|
||||||
|
request({
|
||||||
|
url:'common/auth/feishu/signature',
|
||||||
|
method:'get',
|
||||||
|
data: {url:signUrl,app_id:uni.getStorageSync('fsappid')}
|
||||||
|
}).then(res => {
|
||||||
|
var cfg = res.data.data;
|
||||||
|
window.h5sdk.config({
|
||||||
|
appId: cfg.appId || uni.getStorageSync('fsappid'),
|
||||||
|
timestamp: cfg.timestamp,
|
||||||
|
nonceStr: cfg.nonceStr,
|
||||||
|
signature: cfg.signature,
|
||||||
|
jsApiList: ['shareWebContent','share']
|
||||||
|
})
|
||||||
|
|
||||||
|
window.h5sdk.ready(() => {
|
||||||
|
this._feishuReady = true
|
||||||
|
})
|
||||||
|
window.h5sdk.error((err) => {
|
||||||
|
this._feishuReady = false
|
||||||
|
console.error('Feishu JSSDK error:', err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
// 不要阻塞页面,失败就走 H5 的兜底分享
|
||||||
|
console.error('initFeishuShare failed:', e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequestPrice(payload) {
|
||||||
|
// payload: { item, index }
|
||||||
|
this.priceDialogItem = payload && payload.item ? payload.item : null
|
||||||
|
this.priceDialogIndex = payload && typeof payload.index === 'number' ? payload.index : -1
|
||||||
|
this.priceDialogValue = ''
|
||||||
|
this.priceForm = {
|
||||||
|
trade_term:'',
|
||||||
|
price:"",
|
||||||
|
currency: "USD",
|
||||||
|
lang: "en"
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.inputDialog && this.$refs.inputDialog.open()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// H5 下载:用 a 标签触发
|
||||||
|
downloadByAnchor(url, filename) {
|
||||||
|
try {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename || ''
|
||||||
|
a.target = '_blank'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
} catch (e) {
|
||||||
|
// 兜底:直接打开
|
||||||
|
if (typeof window !== 'undefined') window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
downloadpdf(item) {
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item.id }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadByAnchor(res.data.data.pdf_url, res.data.data.file_name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closePriceDialog() {
|
||||||
|
this.$refs.inputDialog.close()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 只允许数字 + 可选1个小数点(你要“纯整数”也行,我后面给你一行改法)
|
||||||
|
onPriceInput(e) {
|
||||||
|
let v = (e.detail && e.detail.value) ? String(e.detail.value) : String(this.priceForm.price || "")
|
||||||
|
|
||||||
|
// 过滤掉非数字和点
|
||||||
|
v = v.replace(/[^\d.]/g, "")
|
||||||
|
|
||||||
|
// 只保留第一个小数点
|
||||||
|
const parts = v.split(".")
|
||||||
|
if (parts.length > 2) {
|
||||||
|
v = parts[0] + "." + parts.slice(1).join("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去掉开头多余 0(保留 0.xxx)
|
||||||
|
v = v.replace(/^0+(\d)/, "$1")
|
||||||
|
if (v.startsWith(".")) v = "0" + v
|
||||||
|
|
||||||
|
this.priceForm.price = v
|
||||||
|
},
|
||||||
|
|
||||||
|
onCurrencyPickerChange(e) {
|
||||||
|
const idx = Number(e.detail.value || 0)
|
||||||
|
this.currencyIndex = idx
|
||||||
|
this.priceForm.currency = this.currencyOptions[idx]?.value || "USD"
|
||||||
|
},
|
||||||
|
|
||||||
|
onLangChange(e) {
|
||||||
|
this.priceForm.lang = e.detail.value
|
||||||
|
},
|
||||||
|
|
||||||
|
confirmPriceDialog() {
|
||||||
|
if (!this.priceForm.trade_term) {
|
||||||
|
return uni.showToast({ title: "请选择贸易条款", icon: "none" })
|
||||||
|
}
|
||||||
|
// 校验
|
||||||
|
if (!this.priceForm.price) {
|
||||||
|
return uni.showToast({ title: "请输入价格", icon: "none" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
trade_term:this.priceForm.trade_term,
|
||||||
|
price: this.priceForm.price, // 数字字符串
|
||||||
|
currency: this.priceForm.currency, // USD/RUB/AED/EUR
|
||||||
|
lang: this.priceForm.lang // en/ru/es/ar
|
||||||
|
}
|
||||||
|
console.log(payload)
|
||||||
|
this.closePriceDialog()
|
||||||
|
this.dialogInputConfirm(payload)
|
||||||
|
},
|
||||||
|
dialogInputConfirm(val) {
|
||||||
|
const item = this.priceDialogItem
|
||||||
|
const index = this.priceDialogIndex
|
||||||
|
|
||||||
|
if (!item) return
|
||||||
|
if (!val.price) {
|
||||||
|
uni.showToast({ title: '请输入价格', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/produce/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item.id, price:val.price,currency:val.currency,lang:val.lang,trade_term:val.trade_term }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
// 通知刷新列表(你原来就是靠这个事件刷新)
|
||||||
|
this.onSearch()
|
||||||
|
|
||||||
|
this.downloadpdf(item)
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.data.msg || '生成失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onKeywordChange(val) {
|
||||||
|
// val 是输入值(uView 通常会传)
|
||||||
|
this.keyword = val
|
||||||
|
|
||||||
|
// 防抖:300ms 内持续输入只触发一次
|
||||||
|
if (this._kwTimer) clearTimeout(this._kwTimer)
|
||||||
|
this._kwTimer = setTimeout(() => {
|
||||||
|
this.onSearch()
|
||||||
|
}, 300)
|
||||||
|
},
|
||||||
|
onSearch() {
|
||||||
|
this.queryList(this.page,this.pageSize)
|
||||||
|
},
|
||||||
|
queryList(pageNo, pageSize, from) {
|
||||||
|
this.loading = true;
|
||||||
|
var that = this;
|
||||||
|
const params = {
|
||||||
|
current:pageNo,
|
||||||
|
status:1,
|
||||||
|
size:10
|
||||||
|
};
|
||||||
|
params.keyword = this.keyword;
|
||||||
|
params.scene = 'self';
|
||||||
|
request({
|
||||||
|
url:'common/usedcar/list',
|
||||||
|
method:'get',
|
||||||
|
data: params
|
||||||
|
}).then(res => {
|
||||||
|
if(res.data.code ==200){
|
||||||
|
var datas = res.data.data.records;
|
||||||
|
this.$refs.paging.complete(datas);
|
||||||
|
}else{
|
||||||
|
}
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
//
|
||||||
|
})
|
||||||
|
},
|
||||||
|
swipeClick(e,item){
|
||||||
|
let {
|
||||||
|
content
|
||||||
|
} = e;
|
||||||
|
const id = item.id
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/index/publishedit?id=${id}`
|
||||||
|
})
|
||||||
|
// if (content.text === '删除') {
|
||||||
|
// uni.showModal({
|
||||||
|
// title: '提示',
|
||||||
|
// content: '是否删除',
|
||||||
|
// success: res => {
|
||||||
|
// if (res.confirm) {
|
||||||
|
// request({
|
||||||
|
// url:'common/usedcar/destroy',
|
||||||
|
// method:'post',
|
||||||
|
// data: {id:item.id}
|
||||||
|
// }).then(res => {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: res.data.message,
|
||||||
|
// icon: 'none'
|
||||||
|
// });
|
||||||
|
// this.queryList()
|
||||||
|
// })
|
||||||
|
// } else if (res.cancel) {
|
||||||
|
// console.log('用户点击取消');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// const id = item.id
|
||||||
|
// uni.navigateTo({
|
||||||
|
// url: `/pages/index/publishedit?id=${id}`
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tradeTerm{
|
||||||
|
border: 1px solid #eae9e9;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f4f6f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifdef H5 */
|
||||||
|
.page {
|
||||||
|
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
.page-head {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 50px;
|
||||||
|
z-index: 99;
|
||||||
|
// padding: 28rpx 24rpx 18rpx;
|
||||||
|
// background: linear-gradient(180deg, rgba(255, 151, 47, 0.22) 0%, rgba(255, 151, 47, 0.06) 55%, #f4f6f8 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.head-search {
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
border-radius: 18rpx;
|
||||||
|
padding: 20rpx 10px;
|
||||||
|
box-shadow: 0 10rpx 28rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-wrap {
|
||||||
|
padding: 18rpx 24rpx 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loadmore {
|
||||||
|
padding: 18rpx 0 6rpx;
|
||||||
|
}
|
||||||
|
.price-dialog{
|
||||||
|
width: 640rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-title{
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row-col{
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-label{
|
||||||
|
width: 120rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input{
|
||||||
|
flex:1;
|
||||||
|
height: 66rpx;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.pd-input-suffix-wrap{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-with-suffix{
|
||||||
|
padding-right: 180rpx; /* 给右侧币种留空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-currency-suffix{
|
||||||
|
position: absolute;
|
||||||
|
right: 14rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 140rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
::v-deep .uni-select{
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.pd-radio-group{
|
||||||
|
display:flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx 22rpx;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio-text{
|
||||||
|
margin-left: 10rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-actions{
|
||||||
|
display:flex;
|
||||||
|
gap: 18rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-btn{
|
||||||
|
flex:1;
|
||||||
|
height: 84rpx;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-cancel{
|
||||||
|
background:#f5f5f5;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-confirm{
|
||||||
|
background:#3F435B; /* 你喜欢绿色风格 */
|
||||||
|
color:#fff;
|
||||||
|
font-weight:600;
|
||||||
|
}
|
||||||
|
.pd-price-line{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-price{
|
||||||
|
flex: 1;
|
||||||
|
min-width: 240rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<!-- 用户信息卡片 -->
|
||||||
|
<view class="user-card" @click="goToChanginfo">
|
||||||
|
<view class="user-info">
|
||||||
|
<image
|
||||||
|
class="avatar"
|
||||||
|
:src="userInfo.avatar_pull || '/static/image/user.png'"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
<view class="user-details">
|
||||||
|
<text class="nickname">{{ userInfo.name}}</text>
|
||||||
|
<text class="phone">{{ userInfo.name_en}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 功能入口 -->
|
||||||
|
<view class="menu-section">
|
||||||
|
<view class="menu-item" @tap="goToMyPublish" v-if="this.userInfo.role==2">
|
||||||
|
<view class="menu-icon">
|
||||||
|
<u-icon name="list-dot" size="24" color="#3F435B"></u-icon>
|
||||||
|
</view>
|
||||||
|
<text class="menu-text">我的发布</text>
|
||||||
|
<view class="menu-arrow">
|
||||||
|
<u-icon name="arrow-right" size="18" color="#999"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="menu-item" @tap="goToMyPublish" v-if="this.userInfo.role==1">
|
||||||
|
<view class="menu-icon">
|
||||||
|
<u-icon name="list-dot" size="24" color="#3F435B"></u-icon>
|
||||||
|
</view>
|
||||||
|
<text class="menu-text">我的车库</text>
|
||||||
|
<view class="menu-arrow">
|
||||||
|
<u-icon name="arrow-right" size="18" color="#999"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="menu-item" @tap="goToMyPublishpro" v-if="this.userInfo.role_wp==1||this.userInfo.role_wp==2||this.userInfo.role_wp==3">
|
||||||
|
<view class="menu-icon">
|
||||||
|
<u-icon name="list-dot" size="24" color="#3F435B"></u-icon>
|
||||||
|
</view>
|
||||||
|
<text class="menu-text">我的发布</text>
|
||||||
|
<view class="menu-arrow">
|
||||||
|
<u-icon name="arrow-right" size="18" color="#999"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<CustomTabBar class="h5-custom-tabbar" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
import CustomTabBar from '@/custom-tab-bar/index.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CustomTabBar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
userInfo: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
// 页面显示时刷新用户信息
|
||||||
|
this.getUserInfo()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取用户信息
|
||||||
|
getUserInfo() {
|
||||||
|
request({
|
||||||
|
url: 'common/user/info',
|
||||||
|
method: 'get'
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 0 || res.data.code == 200) {
|
||||||
|
this.userInfo = res.data.data
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
// 获取失败时使用默认值
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 跳转到我的发布列表
|
||||||
|
goToMyPublish() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/index/myPublishpro'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
goToMyPublishpro() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/index/myPublishpro'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 跳转到个人信息
|
||||||
|
goToChanginfo() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/index/changinfo'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f4f6f8;
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-card {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-radius: 18rpx;
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #eef2f7;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nickname {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-section {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-radius: 18rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 30rpx;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item:active {
|
||||||
|
background-color: #f9fafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
width: 48rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
// background: #f3f4f6;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-text {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #111827;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-arrow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,907 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<!-- 列表 -->
|
||||||
|
<z-paging ref="paging" v-model="list" @query="queryList" empty-view-text="暂无数据!">
|
||||||
|
<template #top>
|
||||||
|
<!-- 搜索抓取懂车帝 -->
|
||||||
|
<view class="dcd-search">
|
||||||
|
<u-search v-model="urls" placeholder="请输入抓取链接" :show-action="false" shape="round"></u-search>
|
||||||
|
<view class="bind-btn" @tap.stop="onBindByName">抓取</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<!-- <uni-nav-bar leftText=" " :fixed="true" :border="false" color="#fff" backgroundColor="#3F435B" :statusBar="true" title="首页"></uni-nav-bar> -->
|
||||||
|
<!-- 顶部:标题 + 搜索(不想要搜索可直接删除这一块) -->
|
||||||
|
<view class="page-head">
|
||||||
|
<view class="head-search">
|
||||||
|
<u-search
|
||||||
|
v-model="keyword"
|
||||||
|
placeholder="请输入关键词"
|
||||||
|
:show-action="false"
|
||||||
|
shape="round"
|
||||||
|
@change="onKeywordChange"
|
||||||
|
@search="onSearch"
|
||||||
|
@clear="onSearch"
|
||||||
|
/>
|
||||||
|
<view class="statussearch" @click="show=true">
|
||||||
|
<text class="year-text">{{status_name || '状态'}}</text>
|
||||||
|
<u-icon name="arrow-down" size="14" color="#999"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-picker :show="show" :columns="columns" keyName="label" @confirm="onstatus" @cancel="show = false"></u-picker>
|
||||||
|
</view>
|
||||||
|
<view class="list-wrap">
|
||||||
|
<uni-swipe-action-item
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.id"
|
||||||
|
:right-options="options1"
|
||||||
|
@click="swipeClick($event, item)"
|
||||||
|
>
|
||||||
|
<CarCard
|
||||||
|
:item="item"
|
||||||
|
:ismy="true"
|
||||||
|
@pdfchange="onSearch"
|
||||||
|
@request-price="onRequestPrice"
|
||||||
|
@restchange="onSearch"
|
||||||
|
/>
|
||||||
|
</uni-swipe-action-item>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
<uni-popup ref="inputDialog" type="dialog">
|
||||||
|
<view class="price-dialog">
|
||||||
|
<view class="pd-title">设置价格</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">贸易条款</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<uni-data-select
|
||||||
|
v-model="priceForm.trade_term"
|
||||||
|
class="tradeTerm"
|
||||||
|
:localdata="tradeTermOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">价格</view>
|
||||||
|
<view class="pd-price-line">
|
||||||
|
<view class="pd-input-suffix-wrap">
|
||||||
|
<input
|
||||||
|
class="pd-input pd-input-price pd-input-with-suffix"
|
||||||
|
v-model="priceForm.price"
|
||||||
|
type="number"
|
||||||
|
inputmode="decimal"
|
||||||
|
placeholder="请输入数字"
|
||||||
|
@input="onPriceInput"
|
||||||
|
/>
|
||||||
|
<!-- 币种下拉:放在输入框内部右侧(无边框) -->
|
||||||
|
<view class="pd-currency-suffix">
|
||||||
|
<uni-data-select
|
||||||
|
class="pd-currency-select-suffix"
|
||||||
|
v-model="priceForm.currency"
|
||||||
|
:localdata="currencyOptions"
|
||||||
|
:clear="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 语言单选 -->
|
||||||
|
<view class="pd-row">
|
||||||
|
<view class="pd-label">语言</view>
|
||||||
|
<radio-group class="pd-radio-group" @change="onLangChange">
|
||||||
|
<label class="pd-radio" v-for="l in langOptions" :key="l.value">
|
||||||
|
<radio :value="l.value" :checked="priceForm.lang === l.value" />
|
||||||
|
<text class="pd-radio-text">{{ l.text }}</text>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<view class="pd-actions">
|
||||||
|
<view class="pd-btn pd-cancel" @tap="closePriceDialog">取消</view>
|
||||||
|
<view class="pd-btn pd-confirm" @tap="confirmPriceDialog">确认</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
<!-- 抓取信息弹出层 -->
|
||||||
|
<uni-popup ref="crawlDialog" type="dialog">
|
||||||
|
<view class="crawl-dialog">
|
||||||
|
<view class="crawl-title">抓取信息</view>
|
||||||
|
<view class="crawl-content" v-if="crawlLoading">
|
||||||
|
<view class="crawl-loading">正在抓取中...</view>
|
||||||
|
</view>
|
||||||
|
<view class="crawl-content" v-else-if="crawlData">
|
||||||
|
<view class="crawl-item" v-if="crawlData.product_name">
|
||||||
|
<view class="crawl-label">车辆名称</view>
|
||||||
|
<view class="crawl-value">{{ crawlData.product_name }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="crawl-item" v-if="crawlData.source_place">
|
||||||
|
<view class="crawl-label">车源地</view>
|
||||||
|
<view class="crawl-value">{{ crawlData.source_place }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="crawl-item" v-if="crawlData.body_color">
|
||||||
|
<view class="crawl-label">车身颜色</view>
|
||||||
|
<view class="crawl-value">{{ crawlData.body_color }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="crawl-item" v-if="crawlData.plate_time">
|
||||||
|
<view class="crawl-label">上牌时间</view>
|
||||||
|
<view class="crawl-value">{{ crawlData.plate_time }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="crawl-item" v-if="crawlData.mileage">
|
||||||
|
<view class="crawl-label">里程</view>
|
||||||
|
<view class="crawl-value">{{ crawlData.mileage }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="crawl-item" v-if="crawlData.price">
|
||||||
|
<view class="crawl-label">价格</view>
|
||||||
|
<view class="crawl-value">{{ crawlData.price }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="crawl-item" v-if="crawlData.image_pull && crawlData.image_pull.length > 0">
|
||||||
|
<view class="crawl-label">图片</view>
|
||||||
|
<view class="crawl-images">
|
||||||
|
<image
|
||||||
|
v-for="(img, idx) in crawlData.image_pull"
|
||||||
|
:key="idx"
|
||||||
|
:src="img"
|
||||||
|
mode="aspectFill"
|
||||||
|
class="crawl-image"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="crawl-actions">
|
||||||
|
<view class="crawl-btn crawl-confirm1" @tap="closeCrawlDialog">关闭</view>
|
||||||
|
<view class="crawl-btn crawl-confirm" @tap="saveCrawlDialog">保存</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
import CarCard from '@/components/CarCard/CarCard.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CarCard
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
urls:'',
|
||||||
|
show: false,
|
||||||
|
status_id:1,
|
||||||
|
status_name:'',
|
||||||
|
crawlData: null,
|
||||||
|
crawlLoading: false,
|
||||||
|
columns: [
|
||||||
|
[{
|
||||||
|
label: '正常',
|
||||||
|
id: 1
|
||||||
|
}, {
|
||||||
|
label: '已售出',
|
||||||
|
id: 2
|
||||||
|
}, {
|
||||||
|
label: '已归档',
|
||||||
|
id: 3
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
priceDialogItem: null,
|
||||||
|
priceDialogIndex: -1,
|
||||||
|
priceDialogValue: '',
|
||||||
|
options1: [{
|
||||||
|
text: '编辑',
|
||||||
|
style: {
|
||||||
|
backgroundColor: '#007aff'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
keyword: '',
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
loading: false,
|
||||||
|
finished: false,
|
||||||
|
list: [],
|
||||||
|
priceForm: {
|
||||||
|
trade_term:'',
|
||||||
|
price: "", // 只存数字字符串
|
||||||
|
currency: "USD", // USD | RUB | AED | EUR
|
||||||
|
lang: "en" // en | ru | es | ar
|
||||||
|
},
|
||||||
|
currencyOptions: [
|
||||||
|
{ value: "USD", text: "美元" },
|
||||||
|
{ value: "CNY", text: "人民币" },
|
||||||
|
{ value: "RUB", text: "卢布" },
|
||||||
|
{ value: "AED", text: "迪拉姆" },
|
||||||
|
{ value: "EUR", text: "欧元" }
|
||||||
|
],
|
||||||
|
langOptions: [
|
||||||
|
{ text: "英语", value: "en" },
|
||||||
|
{ text: "俄语", value: "ru" },
|
||||||
|
{ text: "西班牙语", value: "es" },
|
||||||
|
{ text: "阿拉伯语", value: "ar" }
|
||||||
|
],
|
||||||
|
tradeTermOptions: [
|
||||||
|
{ value: "FOB", text: "FOB" },
|
||||||
|
{ value: "CIF", text: "CIF" },
|
||||||
|
{ value: "EXW", text: "EXW" },
|
||||||
|
{ value: "DDP", text: "DDP" },
|
||||||
|
{ value: "CIP", text: "CIP" },
|
||||||
|
{ value: "FCA", text: "FCA" },
|
||||||
|
{ value: "CFR", text: "CFR" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.initFeishuShare()
|
||||||
|
// H5:处理分享兜底参数 r(如果路由没命中/经历登录回跳,会先落到首页)
|
||||||
|
// #ifdef H5
|
||||||
|
try {
|
||||||
|
const u = new URL(window.location.href)
|
||||||
|
const r = u.searchParams.get('r')
|
||||||
|
if (r) {
|
||||||
|
const target = decodeURIComponent(r)
|
||||||
|
// 清理地址栏的 r,避免反复跳转
|
||||||
|
u.searchParams.delete('r')
|
||||||
|
window.history.replaceState({}, '', u.toString())
|
||||||
|
// 让首页加载完再跳
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateTo({ url: target })
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isFeishuEnv() {
|
||||||
|
// 飞书/ Lark 客户端内置浏览器 UA 通常包含 Feishu / Lark
|
||||||
|
try {
|
||||||
|
const ua = (navigator.userAgent || '').toLowerCase()
|
||||||
|
return ua.includes('feishu') || ua.includes('lark')
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadFeishuJSSDK() {
|
||||||
|
// 动态加载飞书 H5 JS-SDK(避免你还要改 public/index.html)
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
// 已加载
|
||||||
|
if (typeof window !== 'undefined' && window.h5sdk && window.tt) return resolve(true)
|
||||||
|
// H5 才有 document
|
||||||
|
if (typeof document === 'undefined') return reject(new Error('not in h5 environment'))
|
||||||
|
// 已插入但未 ready
|
||||||
|
const existed = document.querySelector('script[data-feishu-h5sdk="1"]')
|
||||||
|
if (existed) {
|
||||||
|
existed.addEventListener('load', () => resolve(true))
|
||||||
|
existed.addEventListener('error', () => reject(new Error('feishu sdk load error')))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const s = document.createElement('script')
|
||||||
|
s.async = true
|
||||||
|
s.src = 'https://lf-scm-cn.feishucdn.com/lark/op/h5-js-sdk-1.5.44.js'
|
||||||
|
s.onload = () => resolve(true)
|
||||||
|
s.onerror = () => reject(new Error('feishu sdk load error'))
|
||||||
|
document.head.appendChild(s)
|
||||||
|
} catch (e) {
|
||||||
|
reject(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getFeishuSignUrl() {
|
||||||
|
// 飞书签名通常要求“去掉 hash 的完整 URL”
|
||||||
|
try {
|
||||||
|
return window.location.href.split('#')[0]
|
||||||
|
} catch (e) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initFeishuShare() {
|
||||||
|
try {
|
||||||
|
// 确保在飞书环境
|
||||||
|
// if (!this.isFeishuEnv()) return
|
||||||
|
// 动态加载 SDK
|
||||||
|
this.loadFeishuJSSDK()
|
||||||
|
|
||||||
|
// 这里需要后端提供签名接口:返回 { appId, timestamp, nonceStr, signature }
|
||||||
|
// 你可以按你后端习惯改成:request({ url: 'xxx', ... })
|
||||||
|
// const signUrl = encodeURIComponent(this.getFeishuSignUrl())
|
||||||
|
const signUrl = this.getFeishuSignUrl()
|
||||||
|
|
||||||
|
request({
|
||||||
|
url:'common/auth/feishu/signature',
|
||||||
|
method:'get',
|
||||||
|
data: {url:signUrl,app_id:uni.getStorageSync('fsappid')}
|
||||||
|
}).then(res => {
|
||||||
|
var cfg = res.data.data;
|
||||||
|
window.h5sdk.config({
|
||||||
|
appId: cfg.appId || uni.getStorageSync('fsappid'),
|
||||||
|
timestamp: cfg.timestamp,
|
||||||
|
nonceStr: cfg.nonceStr,
|
||||||
|
signature: cfg.signature,
|
||||||
|
jsApiList: ['shareWebContent','share']
|
||||||
|
})
|
||||||
|
|
||||||
|
window.h5sdk.ready(() => {
|
||||||
|
this._feishuReady = true
|
||||||
|
})
|
||||||
|
window.h5sdk.error((err) => {
|
||||||
|
this._feishuReady = false
|
||||||
|
console.error('Feishu JSSDK error:', err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
// 不要阻塞页面,失败就走 H5 的兜底分享
|
||||||
|
console.error('initFeishuShare failed:', e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequestPrice(payload) {
|
||||||
|
// payload: { item, index }
|
||||||
|
this.priceDialogItem = payload && payload.item ? payload.item : null
|
||||||
|
this.priceDialogIndex = payload && typeof payload.index === 'number' ? payload.index : -1
|
||||||
|
this.priceDialogValue = ''
|
||||||
|
this.priceForm = {
|
||||||
|
trade_term:'',
|
||||||
|
price:"",
|
||||||
|
currency: "USD",
|
||||||
|
lang: "en"
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.inputDialog && this.$refs.inputDialog.open()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// H5 下载:用 a 标签触发
|
||||||
|
downloadByAnchor(url, filename) {
|
||||||
|
try {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename || ''
|
||||||
|
a.target = '_blank'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
} catch (e) {
|
||||||
|
// 兜底:直接打开
|
||||||
|
if (typeof window !== 'undefined') window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
downloadpdf(item) {
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item.id }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.downloadByAnchor(res.data.data.pdf_url, res.data.data.file_name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closePriceDialog() {
|
||||||
|
this.$refs.inputDialog.close()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 只允许数字 + 可选1个小数点(你要“纯整数”也行,我后面给你一行改法)
|
||||||
|
onPriceInput(e) {
|
||||||
|
let v = (e.detail && e.detail.value) ? String(e.detail.value) : String(this.priceForm.price || "")
|
||||||
|
|
||||||
|
// 过滤掉非数字和点
|
||||||
|
v = v.replace(/[^\d.]/g, "")
|
||||||
|
|
||||||
|
// 只保留第一个小数点
|
||||||
|
const parts = v.split(".")
|
||||||
|
if (parts.length > 2) {
|
||||||
|
v = parts[0] + "." + parts.slice(1).join("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去掉开头多余 0(保留 0.xxx)
|
||||||
|
v = v.replace(/^0+(\d)/, "$1")
|
||||||
|
if (v.startsWith(".")) v = "0" + v
|
||||||
|
|
||||||
|
this.priceForm.price = v
|
||||||
|
},
|
||||||
|
|
||||||
|
onCurrencyPickerChange(e) {
|
||||||
|
const idx = Number(e.detail.value || 0)
|
||||||
|
this.currencyIndex = idx
|
||||||
|
this.priceForm.currency = this.currencyOptions[idx]?.value || "USD"
|
||||||
|
},
|
||||||
|
|
||||||
|
onLangChange(e) {
|
||||||
|
this.priceForm.lang = e.detail.value
|
||||||
|
},
|
||||||
|
|
||||||
|
confirmPriceDialog() {
|
||||||
|
if (!this.priceForm.trade_term) {
|
||||||
|
return uni.showToast({ title: "请选择贸易条款", icon: "none" })
|
||||||
|
}
|
||||||
|
// 校验
|
||||||
|
if (!this.priceForm.price) {
|
||||||
|
return uni.showToast({ title: "请输入价格", icon: "none" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
trade_term:this.priceForm.trade_term,
|
||||||
|
price: this.priceForm.price, // 数字字符串
|
||||||
|
currency: this.priceForm.currency, // USD/RUB/AED/EUR
|
||||||
|
lang: this.priceForm.lang // en/ru/es/ar
|
||||||
|
}
|
||||||
|
console.log(payload)
|
||||||
|
this.closePriceDialog()
|
||||||
|
this.dialogInputConfirm(payload)
|
||||||
|
},
|
||||||
|
dialogInputConfirm(val) {
|
||||||
|
const item = this.priceDialogItem
|
||||||
|
const index = this.priceDialogIndex
|
||||||
|
|
||||||
|
if (!item) return
|
||||||
|
if (!val.price) {
|
||||||
|
uni.showToast({ title: '请输入价格', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/produce/pdf',
|
||||||
|
method: 'get',
|
||||||
|
data: { id: item.id, price:val.price,currency:val.currency,lang:val.lang,trade_term:val.trade_term }
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
// 通知刷新列表(你原来就是靠这个事件刷新)
|
||||||
|
this.onSearch()
|
||||||
|
|
||||||
|
this.downloadpdf(item)
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.data.msg || '生成失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onKeywordChange(val) {
|
||||||
|
// val 是输入值(uView 通常会传)
|
||||||
|
this.keyword = val
|
||||||
|
|
||||||
|
// 防抖:300ms 内持续输入只触发一次
|
||||||
|
if (this._kwTimer) clearTimeout(this._kwTimer)
|
||||||
|
this._kwTimer = setTimeout(() => {
|
||||||
|
this.onSearch()
|
||||||
|
}, 300)
|
||||||
|
},
|
||||||
|
onSearch() {
|
||||||
|
this.$refs.paging && this.$refs.paging.reload()
|
||||||
|
},
|
||||||
|
queryList(pageNo, pageSize, from) {
|
||||||
|
this.loading = true;
|
||||||
|
var that = this;
|
||||||
|
const params = {
|
||||||
|
current:pageNo,
|
||||||
|
status:this.status_id,
|
||||||
|
size:pageSize
|
||||||
|
};
|
||||||
|
params.keyword = this.keyword;
|
||||||
|
params.scene = 'self';
|
||||||
|
request({
|
||||||
|
url:'common/usedcar/list',
|
||||||
|
method:'get',
|
||||||
|
data: params
|
||||||
|
}).then(res => {
|
||||||
|
if(res.data.code ==200){
|
||||||
|
var datas = res.data.data.records;
|
||||||
|
this.$refs.paging.complete(datas);
|
||||||
|
}else{
|
||||||
|
}
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
//
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onstatus(e){
|
||||||
|
if (e.value && e.value[0]) {
|
||||||
|
const selectedItem = typeof e.value[0] === 'object' ? e.value[0] : { value: e.value[0], label: e.value[0].toString() };
|
||||||
|
this.status_name = selectedItem.label;
|
||||||
|
this.status_id = selectedItem.id;
|
||||||
|
this.show = false;
|
||||||
|
this.$refs.paging && this.$refs.paging.reload()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
swipeClick(e,item){
|
||||||
|
let {
|
||||||
|
content
|
||||||
|
} = e;
|
||||||
|
const id = item.id
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/index/publishedit?id=${id}`
|
||||||
|
})
|
||||||
|
// if (content.text === '删除') {
|
||||||
|
// uni.showModal({
|
||||||
|
// title: '提示',
|
||||||
|
// content: '是否删除',
|
||||||
|
// success: res => {
|
||||||
|
// if (res.confirm) {
|
||||||
|
// request({
|
||||||
|
// url:'common/usedcar/destroy',
|
||||||
|
// method:'post',
|
||||||
|
// data: {id:item.id}
|
||||||
|
// }).then(res => {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: res.data.message,
|
||||||
|
// icon: 'none'
|
||||||
|
// });
|
||||||
|
// this.queryList()
|
||||||
|
// })
|
||||||
|
// } else if (res.cancel) {
|
||||||
|
// console.log('用户点击取消');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// const id = item.id
|
||||||
|
// uni.navigateTo({
|
||||||
|
// url: `/pages/index/publishedit?id=${id}`
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
onBindByName(){
|
||||||
|
if (!this.urls || !this.urls.trim()) {
|
||||||
|
uni.showToast({ title: '请输入抓取链接', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.crawlLoading = true
|
||||||
|
this.crawlData = null
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.crawlDialog && this.$refs.crawlDialog.open()
|
||||||
|
})
|
||||||
|
|
||||||
|
request({
|
||||||
|
url:'common/usedcar/url_crawl',
|
||||||
|
method:'get',
|
||||||
|
data: {url:this.urls}
|
||||||
|
}).then(res => {
|
||||||
|
this.crawlLoading = false
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
this.crawlData = res.data.data || res.data
|
||||||
|
uni.showToast({ title: '抓取成功', icon: 'success' })
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.data.msg || '抓取失败', icon: 'none' })
|
||||||
|
this.crawlData = null
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
this.crawlLoading = false
|
||||||
|
this.crawlData = null
|
||||||
|
console.error('抓取失败', err)
|
||||||
|
uni.showToast({ title: '抓取失败', icon: 'none' })
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closeCrawlDialog() {
|
||||||
|
this.$refs.crawlDialog && this.$refs.crawlDialog.close()
|
||||||
|
this.crawlData = null
|
||||||
|
this.crawlLoading = false
|
||||||
|
},
|
||||||
|
saveCrawlDialog(){
|
||||||
|
function formatCnYearMonth(str) {
|
||||||
|
const match = str.match(/(\d{4})年(\d{1,2})月/)
|
||||||
|
if (!match) return str
|
||||||
|
|
||||||
|
const year = match[1]
|
||||||
|
const month = match[2].padStart(2, '0')
|
||||||
|
|
||||||
|
return `${year}-${month}-01`
|
||||||
|
}
|
||||||
|
const payload = {
|
||||||
|
...this.crawlData,
|
||||||
|
plate_time:formatCnYearMonth(this.crawlData.plate_time),
|
||||||
|
// images 数组 => "url1,url2,url3"
|
||||||
|
images: (this.crawlData.images || [])
|
||||||
|
.map(s => String(s || '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(',')
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url:'common/usedcar/store',
|
||||||
|
method:'post',
|
||||||
|
data:payload
|
||||||
|
}).then(res => {
|
||||||
|
this.$refs.crawlDialog && this.$refs.crawlDialog.close()
|
||||||
|
this.crawlData = null
|
||||||
|
this.crawlLoading = false
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.paging && this.$refs.paging.reload()
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tradeTerm{
|
||||||
|
border: 1px solid #eae9e9;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f4f6f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifdef H5 */
|
||||||
|
.page {
|
||||||
|
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
.dcd-search{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bind-btn {
|
||||||
|
padding: 8px 24px;
|
||||||
|
background: #3F435B;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 28rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bind-btn:active {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-head {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 0px;
|
||||||
|
z-index: 99;
|
||||||
|
// padding: 28rpx 24rpx 18rpx;
|
||||||
|
// background: linear-gradient(180deg, rgba(255, 151, 47, 0.22) 0%, rgba(255, 151, 47, 0.06) 55%, #f4f6f8 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.head-search {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
border-radius: 18rpx;
|
||||||
|
padding: 20rpx 10px;
|
||||||
|
box-shadow: 0 10rpx 28rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
.statussearch{
|
||||||
|
border: 1px solid #eae9e9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.list-wrap {
|
||||||
|
padding: 18rpx 24rpx 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loadmore {
|
||||||
|
padding: 18rpx 0 6rpx;
|
||||||
|
}
|
||||||
|
.price-dialog{
|
||||||
|
width: 640rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-title{
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-row-col{
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-label{
|
||||||
|
width: 120rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input{
|
||||||
|
flex:1;
|
||||||
|
height: 66rpx;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.pd-input-suffix-wrap{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-with-suffix{
|
||||||
|
padding-right: 180rpx; /* 给右侧币种留空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-currency-suffix{
|
||||||
|
position: absolute;
|
||||||
|
right: 14rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 140rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
::v-deep .uni-select{
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.pd-radio-group{
|
||||||
|
display:flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx 22rpx;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-radio-text{
|
||||||
|
margin-left: 10rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-actions{
|
||||||
|
display:flex;
|
||||||
|
gap: 18rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-btn{
|
||||||
|
flex:1;
|
||||||
|
height: 84rpx;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-cancel{
|
||||||
|
background:#f5f5f5;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-confirm{
|
||||||
|
background:#3F435B; /* 你喜欢绿色风格 */
|
||||||
|
color:#fff;
|
||||||
|
font-weight:600;
|
||||||
|
}
|
||||||
|
.pd-price-line{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pd-input-price{
|
||||||
|
flex: 1;
|
||||||
|
min-width: 240rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 抓取信息弹出层样式 */
|
||||||
|
.crawl-dialog {
|
||||||
|
width: 680rpx;
|
||||||
|
max-height: 80vh;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 28rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 60vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-loading {
|
||||||
|
text-align: center;
|
||||||
|
padding: 60rpx 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-item {
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
padding-bottom: 24rpx;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-label {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-value {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-images {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12rpx;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-image {
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 18rpx;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
padding-top: 30rpx;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crawl-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 84rpx;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.crawl-confirm1 {
|
||||||
|
border:1px solid #3F435B;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.crawl-confirm {
|
||||||
|
background: #3F435B;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -0,0 +1,298 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<!-- 列表 -->
|
||||||
|
<z-paging
|
||||||
|
ref="paging"
|
||||||
|
v-model="list"
|
||||||
|
@query="queryList"
|
||||||
|
empty-view-text="暂无发布数据!"
|
||||||
|
>
|
||||||
|
<!-- 顶部:标题 + 搜索 -->
|
||||||
|
<template #top>
|
||||||
|
<view class="page-head">
|
||||||
|
<view class="head-search">
|
||||||
|
<u-search
|
||||||
|
v-model="keyword"
|
||||||
|
placeholder="请输入关键词"
|
||||||
|
:show-action="false"
|
||||||
|
shape="round"
|
||||||
|
@change="onKeywordChange"
|
||||||
|
@search="onSearch"
|
||||||
|
@clear="onSearch"
|
||||||
|
/>
|
||||||
|
<view class="statussearch" @click="show=true">
|
||||||
|
<text class="year-text">{{status_name || '状态'}}</text>
|
||||||
|
<u-icon name="arrow-down" size="14" color="#999"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-picker
|
||||||
|
:show="show"
|
||||||
|
:columns="columns"
|
||||||
|
keyName="label"
|
||||||
|
@confirm="onstatus"
|
||||||
|
@cancel="show = false"
|
||||||
|
></u-picker>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<view class="list-wrap">
|
||||||
|
<uni-swipe-action-item
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.id"
|
||||||
|
:right-options="options1"
|
||||||
|
>
|
||||||
|
<CarCardPro
|
||||||
|
:item="item"
|
||||||
|
:ismy="true"
|
||||||
|
@pdfchange="onSearch"
|
||||||
|
@restchange="onSearch"
|
||||||
|
/>
|
||||||
|
</uni-swipe-action-item>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
import CarCardPro from '@/components/CarCardPro/CarCardPro.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CarCardPro
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
status_id: '',
|
||||||
|
status_name: '',
|
||||||
|
keyword: '',
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
list: [],
|
||||||
|
columns: [
|
||||||
|
{ label: '全部', id: '' },
|
||||||
|
{ label: '正常', id: 1 },
|
||||||
|
{ label: '已售出', id: 2 },
|
||||||
|
{ label: '已归档', id: 3 }
|
||||||
|
],
|
||||||
|
options1: [
|
||||||
|
{
|
||||||
|
text: '编辑',
|
||||||
|
style: {
|
||||||
|
backgroundColor: '#007aff'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '删除',
|
||||||
|
style: {
|
||||||
|
backgroundColor: '#dd524d'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(options) {
|
||||||
|
// 接收从其他页面传来的参数
|
||||||
|
if (options.keyword) {
|
||||||
|
this.keyword = options.keyword
|
||||||
|
}
|
||||||
|
// 首次加载数据
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.onSearch()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取列表数据
|
||||||
|
queryList(pageNo, pageSize) {
|
||||||
|
// 调用专业发布列表接口
|
||||||
|
request({
|
||||||
|
url: 'common/usedcardetail/list',
|
||||||
|
method: 'get',
|
||||||
|
data: {
|
||||||
|
scene: 'self', // 只看自己的发布
|
||||||
|
page: pageNo,
|
||||||
|
limit: pageSize,
|
||||||
|
keyword: this.keyword || '',
|
||||||
|
status: this.status_id || ''
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
const data = res.data.data || {}
|
||||||
|
this.$refs.paging.complete(data.records || [])
|
||||||
|
} else {
|
||||||
|
this.$refs.paging.complete([])
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message || '获取数据失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('[list error]', err)
|
||||||
|
this.$refs.paging.complete([])
|
||||||
|
uni.showToast({
|
||||||
|
title: '获取数据失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
onSearch() {
|
||||||
|
this.$refs.paging.reload()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 关键词变化(防抖)
|
||||||
|
onKeywordChange() {
|
||||||
|
// 防抖处理
|
||||||
|
clearTimeout(this.searchTimer)
|
||||||
|
this.searchTimer = setTimeout(() => {
|
||||||
|
this.onSearch()
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 状态筛选
|
||||||
|
onstatus(e) {
|
||||||
|
const item = e.value[0]
|
||||||
|
this.status_id = item.id
|
||||||
|
this.status_name = item.label
|
||||||
|
this.show = false
|
||||||
|
this.onSearch()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 滑动操作
|
||||||
|
swipeClick(e, item) {
|
||||||
|
if (e.content.text === '编辑') {
|
||||||
|
// 跳转到供应商发布编辑页面
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/index/publisheditPro?id=' + item.id
|
||||||
|
})
|
||||||
|
} else if (e.content.text === '删除') {
|
||||||
|
// 删除确认
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除这条发布吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
this.deleteItem(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除发布
|
||||||
|
deleteItem(item) {
|
||||||
|
uni.showLoading({ title: '删除中...' })
|
||||||
|
|
||||||
|
request({
|
||||||
|
url: 'common/usedcardetail/delete',
|
||||||
|
method: 'post',
|
||||||
|
data: { id: item.id }
|
||||||
|
}).then(res => {
|
||||||
|
uni.hideLoading()
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
// 刷新列表
|
||||||
|
this.onSearch()
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message || '删除失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
uni.hideLoading()
|
||||||
|
console.error('[delete error]', err)
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #F8F8F8;
|
||||||
|
|
||||||
|
/* #ifdef H5 */
|
||||||
|
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-head {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background: #fff;
|
||||||
|
padding: 20rpx 24rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.head-search {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statussearch {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12rpx 20rpx;
|
||||||
|
background: #F5F6F8;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
.year-text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-right: 4rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-wrap {
|
||||||
|
padding: 20rpx 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 列表项过渡动画 */
|
||||||
|
.list-wrap >>> .uni-swipe {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-wrap >>> .uni-swipe_button_group {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-wrap >>> .uni-swipe_box {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空状态样式 */
|
||||||
|
:deep(.z-paging-empty-view) {
|
||||||
|
padding-top: 200rpx !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.z-paging-empty-view-text) {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 加载更多样式 */
|
||||||
|
:deep(.z-paging-loading-more-text) {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,883 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<view class="pages">
|
||||||
|
<!-- <uni-nav-bar leftText=" " :fixed="true" :border="false" color="#fff" backgroundColor="#3F435B" :statusBar="true" title="二手车录入"></uni-nav-bar> -->
|
||||||
|
<view class="content">
|
||||||
|
<view class="cell">
|
||||||
|
<view>产品名称 <text class="red">*</text></view>
|
||||||
|
<view class="right right-bind">
|
||||||
|
<input class="inp" placeholder="请输入车辆的品牌 系列查找车型" v-model="carinfo.product_name" />
|
||||||
|
<view class="bind-btn" @tap.stop="onBindByName">绑定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 绑定结果提示(已绑定时显示) -->
|
||||||
|
<view v-if="bindState.boundProduct" class="bind-tip">
|
||||||
|
<text class="bind-tip-text">已绑定:{{ bindState.boundProduct.name || bindState.boundProduct.product_name || bindState.boundProduct.title || '-' }}</text>
|
||||||
|
<text class="bind-tip-clear" @tap.stop="clearBind">清除</text>
|
||||||
|
</view>
|
||||||
|
<view v-else class="bind-tip">
|
||||||
|
<text>例:比亚迪海狮07DM</text>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="cell">
|
||||||
|
<view>车辆识别码</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入车架号/VIN码" v-model="carinfo.vin" />
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
<view class="cell">
|
||||||
|
<view>车价(¥)</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入车价" v-model="carinfo.price" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell">
|
||||||
|
<view>车源地</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入车源地" v-model="carinfo.source_place" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="cell">
|
||||||
|
<view>上牌地</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入上牌地" v-model="carinfo.plate_place" />
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
<view class="cell">
|
||||||
|
<view>上牌时间</view>
|
||||||
|
<view class="right">
|
||||||
|
<uni-datetime-picker
|
||||||
|
ref="borrowTimePicker"
|
||||||
|
type="date"
|
||||||
|
v-model="carinfo.plate_time"
|
||||||
|
placeholder="请选择时间"
|
||||||
|
:border="false"
|
||||||
|
:clear-icon="false"
|
||||||
|
@change="onBorrowTimeChange"
|
||||||
|
>
|
||||||
|
<view class="custom-datetime-input">
|
||||||
|
<text class="custom-datetime-text" :class="{ 'placeholder': !carinfo.plate_time }">
|
||||||
|
{{ carinfo.plate_time || '请选择时间' }}
|
||||||
|
</text>
|
||||||
|
<uni-icons type="calendar" size="16" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</uni-datetime-picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell">
|
||||||
|
<view>排量</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入排量" v-model="carinfo.displacement" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell">
|
||||||
|
<view>马力</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入马力" v-model="carinfo.power" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell">
|
||||||
|
<view>里程(Km)</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入里程" v-model="carinfo.mileage" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell">
|
||||||
|
<view>车身颜色</view>
|
||||||
|
<view class="right">
|
||||||
|
<input placeholder="请输入车身颜色" v-model="carinfo.body_color" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cont">
|
||||||
|
<view class="conts">产品图</view>
|
||||||
|
<view class="media-upload-wrapper">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="h5-picker-grid">
|
||||||
|
<view class="h5-thumb" v-for="(u, idx) in imagesurl" :key="idx">
|
||||||
|
<image :src="u" mode="aspectFill" class="h5-thumb-img"></image>
|
||||||
|
<view class="h5-thumb-del" @tap.stop="delfn({ index: idx })">删除</view>
|
||||||
|
</view>
|
||||||
|
<view class="upload-icon-wrapper" @tap="pickImagesH5">
|
||||||
|
<image src="/static/image/img.png" class="addimg"></image>
|
||||||
|
<!-- <view class="h5-count">{{ carinfo.images.length }}/{{ maxMedia }}</view> -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<uni-file-picker ref="mediaPicker" :limit="maxMedia" fileMediatype="image" @select="selectMedia" @delete="delfn" >
|
||||||
|
<view class="upload-icon-wrapper">
|
||||||
|
<image src="/static/image/img.png" class="addimg"></image>
|
||||||
|
</view>
|
||||||
|
</uni-file-picker>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cont">
|
||||||
|
<view class="conts">车况介绍</view>
|
||||||
|
<view class="">
|
||||||
|
<textarea auto-height v-model="carinfo.condition_desc" placeholder="请输入车况介绍"/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cont">
|
||||||
|
<view class="conts">附件</view>
|
||||||
|
<view class="media-upload-wrapper">
|
||||||
|
<uni-file-picker ref="mediaPicker1" limit="20" fileMediatype="all" @select="selectMedia1" @delete="delfn1" >
|
||||||
|
<view class="upload-icon-wrapper">
|
||||||
|
<image src="/static/image/photo.png" mode="" class="addimg"></image>
|
||||||
|
</view>
|
||||||
|
</uni-file-picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="zw">
|
||||||
|
<button class="btn" @click="draftadd">提交</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 绑定产品弹框 -->
|
||||||
|
<view v-if="bindState.showDialog" class="bind-mask" @tap="closeBindDialog">
|
||||||
|
<view class="bind-dialog" @tap.stop>
|
||||||
|
<view class="bind-dialog-head">
|
||||||
|
<text class="bind-dialog-title">选择要绑定的产品</text>
|
||||||
|
<text class="bind-dialog-close" @tap="closeBindDialog">×</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 弹框内搜索(仅过滤接口返回列表) -->
|
||||||
|
<view class="bind-search" v-if="bindState.list && bindState.list.length">
|
||||||
|
<input class="bind-search-input" v-model="bindState.keyword" placeholder="搜索产品名称" placeholder-class="bind-search-placeholder" />
|
||||||
|
<text v-if="bindState.keyword" class="bind-search-clear" @tap.stop="bindState.keyword = ''">清除</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<scroll-view scroll-y class="bind-dialog-body">
|
||||||
|
<view v-if="bindState.loading" class="bind-loading">加载中…</view>
|
||||||
|
<view v-else-if="!bindState.list.length" class="bind-empty">未找到匹配的产品</view>
|
||||||
|
<view v-else-if="!filteredBindList.length" class="bind-empty">未找到匹配结果</view>
|
||||||
|
<view v-else>
|
||||||
|
<view
|
||||||
|
class="bind-item"
|
||||||
|
:class="{ active: bindState.selectedId === getBindItemId(it, idx) }"
|
||||||
|
v-for="(it, idx) in filteredBindList"
|
||||||
|
:key="getBindItemId(it, idx)"
|
||||||
|
@tap="selectBind(it, idx)"
|
||||||
|
>
|
||||||
|
<view class="bind-item-main">
|
||||||
|
<text class="bind-item-title">{{ it.name || it.product_name || it.title || ('产品 ' + (idx + 1)) }}</text>
|
||||||
|
<text class="bind-item-sub">{{ formatBindSub(it) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="bind-item-check">
|
||||||
|
<view class="check-dot" v-if="bindState.selectedId === getBindItemId(it, idx)"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<view class="bind-dialog-foot">
|
||||||
|
<view class="btn btn-ghost" @tap="closeBindDialog">取消</view>
|
||||||
|
<view class="btn btn-primary" :class="{ disabled: !bindState.selectedId }" @tap="confirmBind">确认绑定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<CustomTabBar class="h5-custom-tabbar" />
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { request,showToast } from '@/api/apiT.js'
|
||||||
|
import CustomTabBar from '@/custom-tab-bar/index.vue'
|
||||||
|
export default {
|
||||||
|
components:{
|
||||||
|
CustomTabBar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
maxMedia:20,
|
||||||
|
bindState:{
|
||||||
|
showDialog:false,
|
||||||
|
loading:false,
|
||||||
|
list:[],
|
||||||
|
selectedId:'',
|
||||||
|
boundProduct:null,
|
||||||
|
keyword:''
|
||||||
|
},
|
||||||
|
imagesurl:[],
|
||||||
|
carinfo:{
|
||||||
|
product_name:'',
|
||||||
|
vin:'',
|
||||||
|
price:'',
|
||||||
|
source_place:'',
|
||||||
|
plate_place:'',
|
||||||
|
plate_time:'',
|
||||||
|
displacement:'',
|
||||||
|
power:'',
|
||||||
|
body_color:'',
|
||||||
|
images:[],
|
||||||
|
condition_desc:'',
|
||||||
|
mileage:'',
|
||||||
|
attachment:[],
|
||||||
|
crawl_title:'',
|
||||||
|
crawl_brand:'',
|
||||||
|
crawl_series:'',
|
||||||
|
crawl_year:'',
|
||||||
|
crawl_msrp:'',
|
||||||
|
crawl_car_id:'',
|
||||||
|
crawl_brand_id:'',
|
||||||
|
crawl_series_id:''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 弹框内搜索过滤(仅前端过滤接口返回结果,不重复请求)
|
||||||
|
filteredBindList() {
|
||||||
|
const list = Array.isArray(this.bindState.list) ? this.bindState.list : []
|
||||||
|
const kw = String(this.bindState.keyword || '').trim().toLowerCase()
|
||||||
|
if (!kw) return list
|
||||||
|
return list.filter((it, idx) => {
|
||||||
|
const id = String(it.id || it.product_id || it.code || idx).toLowerCase()
|
||||||
|
const name = String(it.name || it.product_name || it.title || '').toLowerCase()
|
||||||
|
const sub = String(this.formatBindSub(it) || '').toLowerCase()
|
||||||
|
return id.includes(kw) || name.includes(kw) || sub.includes(kw)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onBorrowTimeChange(e) {
|
||||||
|
this.carinfo.plate_time = e
|
||||||
|
},
|
||||||
|
// 绑定:根据输入的“产品名称”拉取候选产品
|
||||||
|
onBindByName() {
|
||||||
|
const name = String(this.carinfo.product_name || '').trim()
|
||||||
|
if (!name) {
|
||||||
|
return uni.showToast({ title: '请先输入产品名称', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开弹框 + loading
|
||||||
|
this.bindState.showDialog = true
|
||||||
|
this.bindState.loading = true
|
||||||
|
this.bindState.list = []
|
||||||
|
this.bindState.selectedId = ''
|
||||||
|
this.bindState.keyword = ''
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO:把这里的接口地址换成你真实的“按名称搜索产品”接口
|
||||||
|
* - 传参:name(产品名称)
|
||||||
|
* - 返回:数组(可能多个匹配)
|
||||||
|
*/
|
||||||
|
request({
|
||||||
|
url: 'common/usedcar/crawl', // <== 这里改成你的真实接口
|
||||||
|
method: 'get',
|
||||||
|
data: { keyword:name }
|
||||||
|
}).then(res => {
|
||||||
|
if(res.data.code ==200){
|
||||||
|
this.bindState.list = res.data.data.model
|
||||||
|
}else{
|
||||||
|
uni.showToast({ title: res.data.message, icon: 'none' })
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
uni.showToast({ title: '拉取产品失败,请稍后重试', icon: 'none' })
|
||||||
|
}).finally(() => {
|
||||||
|
this.bindState.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closeBindDialog() {
|
||||||
|
this.bindState.showDialog = false
|
||||||
|
this.bindState.keyword = ''
|
||||||
|
},
|
||||||
|
getBindItemId(it, idx) {
|
||||||
|
return String(it.id || it.product_id || it.requisition_item_id || it.code || idx)
|
||||||
|
},
|
||||||
|
selectBind(it, idx) {
|
||||||
|
this.bindState.selectedId = this.getBindItemId(it, idx)
|
||||||
|
this.bindState._selected = it
|
||||||
|
},
|
||||||
|
formatBindSub(it) {
|
||||||
|
// 按你接口字段自行补充展示:编码/规格/分类/库存等
|
||||||
|
const parts = []
|
||||||
|
if (it.sku || it.code) parts.push('编码:' + (it.sku || it.code))
|
||||||
|
if (it.category_name) parts.push('分类:' + it.category_name)
|
||||||
|
if (it.price) parts.push('价格:' + it.price)
|
||||||
|
return parts.join(' · ')
|
||||||
|
},
|
||||||
|
confirmBind() {
|
||||||
|
if (!this.bindState.selectedId || !this.bindState._selected) return
|
||||||
|
|
||||||
|
const it = this.bindState._selected
|
||||||
|
|
||||||
|
// 写入“已绑定”状态(你后续提交表单时可直接带上 bound_product_id)
|
||||||
|
this.bindState.boundProduct = it
|
||||||
|
this.carinfo.crawl_title = it.title
|
||||||
|
this.carinfo.crawl_brand = it.brand_name
|
||||||
|
this.carinfo.crawl_series = it.series_name
|
||||||
|
this.carinfo.crawl_year = it.year
|
||||||
|
this.carinfo.crawl_msrp = it.msrp
|
||||||
|
this.carinfo.crawl_car_id = it.car_id
|
||||||
|
this.carinfo.crawl_brand_id = it.brand_id
|
||||||
|
this.carinfo.crawl_series_id = it.series_id
|
||||||
|
console.log(it)
|
||||||
|
this.closeBindDialog()
|
||||||
|
uni.showToast({ title: '绑定成功', icon: 'none' })
|
||||||
|
},
|
||||||
|
clearBind() {
|
||||||
|
this.carinfo.crawl_title = ''
|
||||||
|
this.carinfo.crawl_brand = ''
|
||||||
|
this.carinfo.crawl_series = ''
|
||||||
|
this.carinfo.crawl_year = ''
|
||||||
|
this.carinfo.crawl_msrp = ''
|
||||||
|
this.carinfo.crawl_car_id = ''
|
||||||
|
this.carinfo.crawl_brand_id = ''
|
||||||
|
this.carinfo.crawl_series_id = ''
|
||||||
|
this.bindState.boundProduct = null
|
||||||
|
uni.showToast({ title: '已清除绑定', icon: 'none' })
|
||||||
|
},
|
||||||
|
|
||||||
|
uploadfn(imgUrl,scene){
|
||||||
|
uni.showLoading({
|
||||||
|
title: '上传中'
|
||||||
|
});
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.uploadFile({
|
||||||
|
url: 'https://userdcar-server.hnxinyouhe.com/upload?scene='+scene,
|
||||||
|
filePath: imgUrl,
|
||||||
|
name: 'file',
|
||||||
|
header:{'Fdesk-Auth-Token': uni.getStorageSync('token'),'Fdesk-Login-Type': 'feishu','Fdesk-System-Code':'fdesk'},
|
||||||
|
success: (uploadFileRes) => {
|
||||||
|
const res = JSON.parse(uploadFileRes.data || '{}')
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title:res.message,
|
||||||
|
icon:'none'
|
||||||
|
})
|
||||||
|
if(res && res.data && res.data.file_name){
|
||||||
|
resolve(res.data.file_name)
|
||||||
|
}else{
|
||||||
|
reject('上传失败')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => reject(err)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
uploadfndile(imgUrl,scene){
|
||||||
|
uni.showLoading({
|
||||||
|
title: '上传中'
|
||||||
|
});
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.uploadFile({
|
||||||
|
url: 'https://userdcar-server.hnxinyouhe.com/upload?scene='+scene,
|
||||||
|
filePath: imgUrl,
|
||||||
|
name: 'file',
|
||||||
|
header:{'Fdesk-Auth-Token': uni.getStorageSync('token'),'Fdesk-Login-Type': 'feishu','Fdesk-System-Code':'fdesk'},
|
||||||
|
success: (uploadFileRes) => {
|
||||||
|
const res = JSON.parse(uploadFileRes.data || '{}')
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title:res.message,
|
||||||
|
icon:'none'
|
||||||
|
})
|
||||||
|
if(res && res.data && res.data.file_name){
|
||||||
|
resolve(res.data)
|
||||||
|
}else{
|
||||||
|
reject(res)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => reject(err)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// H5 专用:绕过 uni.chooseImage/chooseMedia 的 9 张限制,使用 uni.chooseFile 支持最多 20 个
|
||||||
|
pickImagesH5() {
|
||||||
|
// const remain = this.maxMedia - this.carinfo.images.length
|
||||||
|
// if (remain <= 0) {
|
||||||
|
// return uni.showToast({ title: `最多只能上传${this.maxMedia}张`, icon: 'none' })
|
||||||
|
// }
|
||||||
|
uni.chooseFile({
|
||||||
|
count: 100,
|
||||||
|
type: 'image',
|
||||||
|
success: (res) => {
|
||||||
|
const paths = (res.tempFilePaths || (res.tempFiles || []).map(it => it.path)).filter(Boolean)
|
||||||
|
if (!paths.length) return
|
||||||
|
Promise.all(paths.map(p => this.uploadfndile(p, 'usedcarimg'))).then(urls => {
|
||||||
|
urls.forEach(url => {
|
||||||
|
this.imagesurl.push(url.file_url)
|
||||||
|
this.carinfo.images.push(url.file_name)
|
||||||
|
})
|
||||||
|
}).catch((e) => {
|
||||||
|
uni.showToast({ title: e.message, icon: 'none' })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
pickAttachmentH5() {
|
||||||
|
const remain = this.maxMedia - this.carinfo.attachment.length
|
||||||
|
if (remain <= 0) {
|
||||||
|
return uni.showToast({ title: `最多只能上传${this.maxMedia}个`, icon: 'none' })
|
||||||
|
}
|
||||||
|
uni.chooseFile({
|
||||||
|
count: remain,
|
||||||
|
type: 'all',
|
||||||
|
success: (res) => {
|
||||||
|
const files = res.tempFiles || []
|
||||||
|
const paths = (res.tempFilePaths || files.map(it => it.path)).filter(Boolean)
|
||||||
|
if (!paths.length) return
|
||||||
|
Promise.all(paths.map(p => this.uploadfndile(p, 'usedcarfile'))).then(urls => {
|
||||||
|
urls.forEach((url, idx) => {
|
||||||
|
const obj = {}
|
||||||
|
obj.name = url.original_name || files[idx]?.name || '附件'
|
||||||
|
obj.src = url.file_name
|
||||||
|
this.carinfo.attachment.push(obj)
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
uni.showToast({ title:e.message, icon: 'none' })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
selectMedia(e){
|
||||||
|
const allowCount = this.maxMedia - this.carinfo.images.length
|
||||||
|
const tempFilePaths = e.tempFilePaths || (e.tempFiles || []).map(item => item.path || item.url)
|
||||||
|
const paths = tempFilePaths.slice(0, allowCount)
|
||||||
|
if(paths.length === 0){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Promise.all(paths.map(p => this.uploadfn(p,'usedcarimg'))).then(urls => {
|
||||||
|
urls.forEach(url => {
|
||||||
|
this.carinfo.images.push(url)
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title:'图片上传失败,请重试',
|
||||||
|
icon:'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
delfn(e){
|
||||||
|
this.imagesurl.splice(e.index, 1)
|
||||||
|
this.carinfo.images.splice(e.index, 1)
|
||||||
|
},
|
||||||
|
selectMedia1(e){
|
||||||
|
const allowCount = this.maxMedia - this.carinfo.attachment.length
|
||||||
|
const tempFilePaths = e.tempFilePaths || (e.tempFiles || []).map(item => item.path || item.url)
|
||||||
|
const paths = tempFilePaths.slice(0, allowCount)
|
||||||
|
if(paths.length === 0){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Promise.all(paths.map(p => this.uploadfndile(p,'usedcarfile'))).then(urls => {
|
||||||
|
urls.forEach(url => {
|
||||||
|
const obj={}
|
||||||
|
obj.name =url.original_name
|
||||||
|
obj.src =url.file_name
|
||||||
|
this.carinfo.attachment.push(obj)
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title:'图片上传失败,请重试',
|
||||||
|
icon:'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
delfn1(e){
|
||||||
|
this.carinfo.attachment.splice(e.index, 1)
|
||||||
|
},
|
||||||
|
draftadd(){
|
||||||
|
const payload = {
|
||||||
|
...this.carinfo,
|
||||||
|
// images 数组 => "url1,url2,url3"
|
||||||
|
images: (this.carinfo.images || [])
|
||||||
|
.map(s => String(s || '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(',')
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url:'common/usedcar/store',
|
||||||
|
method:'post',
|
||||||
|
data:payload
|
||||||
|
}).then(res => {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/index/index',// 替换为你要跳 转的页面路径
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.pages{
|
||||||
|
max-width: 650px;
|
||||||
|
}
|
||||||
|
/* #ifdef H5 */
|
||||||
|
.pages{
|
||||||
|
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
.uniui-right{
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
|
.red{
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
// margin: 20px 12px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.zw{
|
||||||
|
height: 120px;
|
||||||
|
}
|
||||||
|
.cont{
|
||||||
|
position: relative;
|
||||||
|
padding: 18px 20px;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.conts{
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
.media-upload-wrapper{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
.cell{
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content:space-between;
|
||||||
|
padding: 14px 10px;
|
||||||
|
/* border-bottom: 1px solid #C3C3C3; */
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.cont::after,.cell::after{
|
||||||
|
content : '';
|
||||||
|
position : absolute;
|
||||||
|
width : 200%;
|
||||||
|
height : 200%;
|
||||||
|
top : 0;
|
||||||
|
left : 0;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
border-width: 0;
|
||||||
|
border-bottom-width:1px;
|
||||||
|
border-style : solid;
|
||||||
|
transform : scale(0.5, 0.5);
|
||||||
|
border-radius : 1px;
|
||||||
|
box-sizing : border-box;
|
||||||
|
pointer-events : none;
|
||||||
|
border-color:#C3C3C3;
|
||||||
|
}
|
||||||
|
.cell1{
|
||||||
|
display: flex;
|
||||||
|
justify-content:space-between;
|
||||||
|
padding: 18px 20px;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.right{
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.select{
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.foot{
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 120px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.btn{
|
||||||
|
background-color: #3F435B;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50px;
|
||||||
|
width: 92%;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
margin: 15px 4%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actives{
|
||||||
|
background-color: #dfdfdf;
|
||||||
|
}
|
||||||
|
.text{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 10px 15px 0px;
|
||||||
|
.qd{
|
||||||
|
color: #3471FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.popup-content {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-list {
|
||||||
|
max-height: 400rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item {
|
||||||
|
padding: 20rpx;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.addimg{
|
||||||
|
width: 215rpx;
|
||||||
|
height: 215rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 产品名称 + 绑定按钮 */
|
||||||
|
.right-bind{
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
width: 74%;
|
||||||
|
}
|
||||||
|
.right-bind .inp{
|
||||||
|
flex: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
.bind-btn{
|
||||||
|
margin-left: 16rpx;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
line-height: 56rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background: #2E6CF6;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
.bind-tip{
|
||||||
|
// margin: 0 24rpx 16rpx;
|
||||||
|
padding: 12rpx 18rpx;
|
||||||
|
// border-radius: 12rpx;
|
||||||
|
background: #F3F6FF;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.bind-tip-text{
|
||||||
|
color: #2B3A55;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
.bind-tip-clear{
|
||||||
|
color: #2E6CF6;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 弹框搜索 */
|
||||||
|
.bind-search{
|
||||||
|
margin: 5px 24rpx 16rpx;
|
||||||
|
padding: 12rpx 18rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background: #F3F6FF;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.bind-search-input{
|
||||||
|
flex: 1;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.bind-search-placeholder{
|
||||||
|
color: #9AA6BF;
|
||||||
|
}
|
||||||
|
.bind-search-clear{
|
||||||
|
margin-left: 16rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #2E6CF6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 绑定弹框 */
|
||||||
|
.bind-mask{
|
||||||
|
position: fixed;
|
||||||
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
|
background: rgba(0,0,0,0.45);
|
||||||
|
z-index: 999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 40rpx;
|
||||||
|
}
|
||||||
|
.bind-dialog{
|
||||||
|
width: 100%;
|
||||||
|
max-width: 680rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.bind-dialog-head{
|
||||||
|
height: 96rpx;
|
||||||
|
padding: 0 24rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
.bind-dialog-title{
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111;
|
||||||
|
}
|
||||||
|
.bind-dialog-close{
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #999;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.bind-dialog-body{
|
||||||
|
max-height: 720rpx;
|
||||||
|
padding: 12rpx 0;
|
||||||
|
}
|
||||||
|
.bind-loading,.bind-empty{
|
||||||
|
padding: 40rpx 24rpx;
|
||||||
|
color: #888;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
.bind-item{
|
||||||
|
padding: 18rpx 24rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.bind-item.active{
|
||||||
|
background: #F3F6FF;
|
||||||
|
}
|
||||||
|
.bind-item-main{
|
||||||
|
flex: 1;
|
||||||
|
padding-right: 16rpx;
|
||||||
|
}
|
||||||
|
.bind-item-title{
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #222;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.bind-item-sub{
|
||||||
|
margin-top: 6rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #777;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.bind-item-check{
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2rpx solid #2E6CF6;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.check-dot{
|
||||||
|
width: 22rpx;
|
||||||
|
height: 22rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #2E6CF6;
|
||||||
|
}
|
||||||
|
.bind-dialog-foot{
|
||||||
|
padding: 16rpx 24rpx 22rpx;
|
||||||
|
display: flex;
|
||||||
|
gap: 16rpx;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
.btn{
|
||||||
|
flex: 1;
|
||||||
|
height: 76rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
.btn-ghost{
|
||||||
|
background: #F5F6F8;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.btn-primary{
|
||||||
|
background: #2E6CF6;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.btn-primary.disabled{
|
||||||
|
opacity: .45;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* H5 自定义选择器:用于突破 9 个限制(H5 最多 20) */
|
||||||
|
.h5-picker-grid{
|
||||||
|
display:flex;
|
||||||
|
flex-wrap:wrap;
|
||||||
|
gap: 16rpx;
|
||||||
|
align-items:flex-start;
|
||||||
|
}
|
||||||
|
.h5-thumb{
|
||||||
|
width: 210rpx;
|
||||||
|
height: 210rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
overflow:hidden;
|
||||||
|
position: relative;
|
||||||
|
background: #f6f6f6;
|
||||||
|
}
|
||||||
|
.h5-thumb-img{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.h5-thumb-del{
|
||||||
|
position:absolute;
|
||||||
|
right: 8rpx;
|
||||||
|
top: 8rpx;
|
||||||
|
background: rgba(0,0,0,0.45);
|
||||||
|
color:#fff;
|
||||||
|
font-size: 22rpx;
|
||||||
|
padding: 6rpx 10rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
}
|
||||||
|
.h5-count{
|
||||||
|
margin-top: 8rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color:#999;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
.h5-attach-grid .h5-attach{
|
||||||
|
width: 210rpx;
|
||||||
|
min-height: 120rpx;
|
||||||
|
padding: 16rpx;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background: #fafafa;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.h5-attach-name{
|
||||||
|
font-size: 24rpx;
|
||||||
|
color:#333;
|
||||||
|
word-break: break-all;
|
||||||
|
padding-right: 60rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
<template>
|
||||||
|
<view class="auth-page">
|
||||||
|
<view class="auth-card">
|
||||||
|
<view v-if="status === 'loading'">
|
||||||
|
<view class="spinner"></view>
|
||||||
|
<view class="text-wrap">
|
||||||
|
<text class="title">{{ title }}</text>
|
||||||
|
<text class="desc">{{ desc }}<text class="dots">{{ dots }}</text></text>
|
||||||
|
</view>
|
||||||
|
<view class="progress">
|
||||||
|
<view class="bar"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else class="error-wrap">
|
||||||
|
<uni-icons type="clear" size="44" color="#ff4d4f"></uni-icons>
|
||||||
|
<text class="title">登录失败</text>
|
||||||
|
<text class="desc">{{ errorMsg }}</text>
|
||||||
|
<button class="retry-btn" @click="retry">重试</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
import { saveRoles } from '@/common/role.js'
|
||||||
|
import { getVisibleTabBar } from '@/common/tabbar.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
status: 'loading',
|
||||||
|
title: '正在完成登录',
|
||||||
|
desc: '处理中',
|
||||||
|
dots: '',
|
||||||
|
errorMsg: '请稍后重试',
|
||||||
|
_dotTimer: null,
|
||||||
|
minStayMs: 600,
|
||||||
|
_startedAt: 0,
|
||||||
|
_code: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(options) {
|
||||||
|
this._startedAt = Date.now()
|
||||||
|
this.startDots()
|
||||||
|
// #ifdef H5
|
||||||
|
this._code = options.code || ''
|
||||||
|
// 支持从回调参数里带 redirect(有些场景会拼到回调地址上)
|
||||||
|
const redirect = options.redirect || options.r || ''
|
||||||
|
if (redirect) {
|
||||||
|
try {
|
||||||
|
uni.setStorageSync('post_login_redirect', decodeURIComponent(redirect))
|
||||||
|
} catch (e) {
|
||||||
|
uni.setStorageSync('post_login_redirect', redirect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
if (!this._code) {
|
||||||
|
this.fail('缺少 code 参数')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.logins(this._code)
|
||||||
|
},
|
||||||
|
onUnload() {
|
||||||
|
this.stopDots()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
startDots() {
|
||||||
|
this.stopDots()
|
||||||
|
let n = 0
|
||||||
|
this._dotTimer = setInterval(() => {
|
||||||
|
n = (n + 1) % 4
|
||||||
|
this.dots = '.'.repeat(n)
|
||||||
|
}, 350)
|
||||||
|
},
|
||||||
|
stopDots() {
|
||||||
|
if (this._dotTimer) {
|
||||||
|
clearInterval(this._dotTimer)
|
||||||
|
this._dotTimer = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail(msg) {
|
||||||
|
this.status = 'error'
|
||||||
|
this.errorMsg = msg || '请稍后重试'
|
||||||
|
uni.showToast({ title: msg || '登录失败', icon: 'none' })
|
||||||
|
},
|
||||||
|
async logins(code) {
|
||||||
|
try {
|
||||||
|
this.title = '正在交换登录凭证'
|
||||||
|
this.desc = '请稍候'
|
||||||
|
|
||||||
|
const res = await request({
|
||||||
|
url: 'common/auth/login',
|
||||||
|
method: 'POST',
|
||||||
|
loginType: 'feishu', // 飞书登录
|
||||||
|
data: { feishu_code: code, app_id: uni.getStorageSync('fsappid'), is_pc: 0 }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res.data.code !== 200) {
|
||||||
|
throw new Error(res.data.message || '登录失败')
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = res.data.data
|
||||||
|
|
||||||
|
// 保存登录类型
|
||||||
|
uni.setStorageSync('loginType', 'feishu')
|
||||||
|
|
||||||
|
// 统一使用 union_id 作为 token(与PC端保持一致)
|
||||||
|
const token = data.union_id || data.token
|
||||||
|
if (!token) {
|
||||||
|
throw new Error('未获取到 token')
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.setStorageSync('token', token)
|
||||||
|
|
||||||
|
// 保存用户信息
|
||||||
|
const userInfo = {
|
||||||
|
...data,
|
||||||
|
token: token
|
||||||
|
}
|
||||||
|
uni.setStorageSync('userInfo', userInfo)
|
||||||
|
|
||||||
|
// 处理角色信息(统一使用 role.js 工具)
|
||||||
|
if (data.role) {
|
||||||
|
saveRoles(data.role, data.role_wp)
|
||||||
|
|
||||||
|
// 通知自定义 TabBar 刷新
|
||||||
|
uni.$emit && uni.$emit('userRoleChanged')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.title = '登录成功'
|
||||||
|
this.desc = '正在进入页面'
|
||||||
|
|
||||||
|
this.goRedirectSmooth()
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[feishu callback] error:', err)
|
||||||
|
this.fail(err?.message || '登录失败')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
goRedirectSmooth() {
|
||||||
|
const elapsed = Date.now() - this._startedAt
|
||||||
|
const wait = Math.max(0, this.minStayMs - elapsed)
|
||||||
|
setTimeout(() => {
|
||||||
|
// 获取用户可见的TabBar列表
|
||||||
|
const visibleTabs = getVisibleTabBar()
|
||||||
|
// 检查是否包含首页Tab
|
||||||
|
const hasIndexTab = visibleTabs.some(tab => tab.pagePath === 'pages/index/index')
|
||||||
|
// 默认跳转目标:有首页进入首页,否则进入我的页面
|
||||||
|
const defaultTarget = hasIndexTab ? '/pages/index/index' : '/pages/index/mine'
|
||||||
|
// 优先使用存储的跳转地址
|
||||||
|
const target = uni.getStorageSync('post_login_redirect') || defaultTarget
|
||||||
|
uni.removeStorageSync('post_login_redirect')
|
||||||
|
uni.reLaunch({ url: target })
|
||||||
|
}, wait)
|
||||||
|
},
|
||||||
|
retry() {
|
||||||
|
this.status = 'loading'
|
||||||
|
this.title = '正在完成登录'
|
||||||
|
this.desc = '处理中'
|
||||||
|
this.startDots()
|
||||||
|
if (this._code) this.logins(this._code)
|
||||||
|
else this.fail('缺少 code 参数')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.auth-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: linear-gradient(180deg, #FF972F 0%, #F4F6F8 38%, #F4F6F8 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 640rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 44rpx 36rpx 32rpx;
|
||||||
|
box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
width: 88rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 8rpx solid rgba(255,151,47, 0.18);
|
||||||
|
border-top-color: #FF972F;
|
||||||
|
animation: spin 0.9s linear infinite;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-wrap {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: block;
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #1f2937;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
display: block;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dots {
|
||||||
|
display: inline-block;
|
||||||
|
width: 40rpx;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
width: 100%;
|
||||||
|
height: 10rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: rgba(255,151,47, 0.10);
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress .bar {
|
||||||
|
height: 100%;
|
||||||
|
width: 40%;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: rgba(255,151,47, 0.55);
|
||||||
|
animation: move 1.1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-btn {
|
||||||
|
margin-top: 24rpx;
|
||||||
|
width: 240rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
line-height: 72rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: #FF972F;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move {
|
||||||
|
0% { transform: translateX(-60%); }
|
||||||
|
50% { transform: translateX(140%); }
|
||||||
|
100% { transform: translateX(-60%); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "customicons"; /* Project id 2878519 */
|
||||||
|
src:url('/static/customicons.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.customicons {
|
||||||
|
font-family: "customicons" !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.youxi:before {
|
||||||
|
content: "\e60e";
|
||||||
|
}
|
||||||
|
|
||||||
|
.wenjian:before {
|
||||||
|
content: "\e60f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.zhuanfa:before {
|
||||||
|
content: "\e610";
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "iconfont"; /* Project id */
|
||||||
|
src: url('@/static/iconfont.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-family: "iconfont" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-link:before {
|
||||||
|
content: "\e772";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-poweroff:before {
|
||||||
|
content: "\e774";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-safety-certificate:before {
|
||||||
|
content: "\e776";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-chart-pie-alt:before {
|
||||||
|
content: "\e78c";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-kongxincai:before {
|
||||||
|
content: "\e642";
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 557 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 970 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 640 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,17 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
export const useCounterStore = defineStore('counter', {
|
||||||
|
state: () => ({
|
||||||
|
count: 0
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
doubleCount: (state) => state.count * 2
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
increment() {
|
||||||
|
this.count++
|
||||||
|
},
|
||||||
|
decrement() {
|
||||||
|
this.count--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
// #ifndef VUE3
|
||||||
|
import Vue from 'vue'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
Vue.use(Vuex)
|
||||||
|
const store = new Vuex.Store({
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef VUE3
|
||||||
|
import { createStore } from 'vuex'
|
||||||
|
const store = createStore({
|
||||||
|
// #endif
|
||||||
|
state: {
|
||||||
|
hasLogin: false,
|
||||||
|
isUniverifyLogin: false,
|
||||||
|
loginProvider: "",
|
||||||
|
openid: null,
|
||||||
|
testvuex: false,
|
||||||
|
colorIndex: 0,
|
||||||
|
colorList: ['#FF0000', '#00FF00', '#0000FF'],
|
||||||
|
noMatchLeftWindow: true,
|
||||||
|
active: 'componentPage',
|
||||||
|
leftWinActive: '/pages/component/view/view',
|
||||||
|
activeOpen: '',
|
||||||
|
menu: [],
|
||||||
|
univerifyErrorMsg: '',
|
||||||
|
// vuex测试例使用
|
||||||
|
username: "foo",
|
||||||
|
sex: "男",
|
||||||
|
age: 10
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
login(state, provider) {
|
||||||
|
state.hasLogin = true;
|
||||||
|
state.loginProvider = provider;
|
||||||
|
},
|
||||||
|
logout(state) {
|
||||||
|
state.hasLogin = false
|
||||||
|
state.openid = null
|
||||||
|
},
|
||||||
|
setOpenid(state, openid) {
|
||||||
|
state.openid = openid
|
||||||
|
},
|
||||||
|
setTestTrue(state) {
|
||||||
|
state.testvuex = true
|
||||||
|
},
|
||||||
|
setTestFalse(state) {
|
||||||
|
state.testvuex = false
|
||||||
|
},
|
||||||
|
setColorIndex(state, index) {
|
||||||
|
state.colorIndex = index
|
||||||
|
},
|
||||||
|
setMatchLeftWindow(state, matchLeftWindow) {
|
||||||
|
state.noMatchLeftWindow = !matchLeftWindow
|
||||||
|
},
|
||||||
|
setActive(state, tabPage) {
|
||||||
|
state.active = tabPage
|
||||||
|
},
|
||||||
|
setLeftWinActive(state, leftWinActive) {
|
||||||
|
state.leftWinActive = leftWinActive
|
||||||
|
},
|
||||||
|
setActiveOpen(state, activeOpen) {
|
||||||
|
state.activeOpen = activeOpen
|
||||||
|
},
|
||||||
|
setMenu(state, menu) {
|
||||||
|
state.menu = menu
|
||||||
|
},
|
||||||
|
setUniverifyLogin(state, payload) {
|
||||||
|
typeof payload !== 'boolean' ? payload = !!payload : '';
|
||||||
|
state.isUniverifyLogin = payload;
|
||||||
|
},
|
||||||
|
setUniverifyErrorMsg(state,payload = ''){
|
||||||
|
state.univerifyErrorMsg = payload
|
||||||
|
},
|
||||||
|
// vuex测试例使用
|
||||||
|
increment(state) {
|
||||||
|
state.age++;
|
||||||
|
},
|
||||||
|
incrementTen(state, payload) {
|
||||||
|
state.age += payload.amount
|
||||||
|
},
|
||||||
|
resetAge(state){
|
||||||
|
state.age = 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
currentColor(state) {
|
||||||
|
return state.colorList[state.colorIndex]
|
||||||
|
},
|
||||||
|
// vuex测试例使用
|
||||||
|
doubleAge(state) {
|
||||||
|
return state.age * 2;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
// vuex测试例使用
|
||||||
|
incrementAsync(context , payload) {
|
||||||
|
context.commit('incrementTen',payload)
|
||||||
|
},
|
||||||
|
// lazy loading openid
|
||||||
|
getUserOpenId: async function({
|
||||||
|
commit,
|
||||||
|
state
|
||||||
|
}) {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
if (state.openid) {
|
||||||
|
resolve(state.openid)
|
||||||
|
} else {
|
||||||
|
uni.login({
|
||||||
|
success: (data) => {
|
||||||
|
commit('login')
|
||||||
|
setTimeout(function() { //模拟异步请求服务器获取 openid
|
||||||
|
const openid = '123456789'
|
||||||
|
console.log('uni.request mock openid[' + openid + ']');
|
||||||
|
commit('setOpenid', openid)
|
||||||
|
resolve(openid)
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log('uni.login 接口调用失败,将无法正常使用开放接口等服务', err)
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getPhoneNumber: function({
|
||||||
|
commit
|
||||||
|
}, univerifyInfo) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.request({
|
||||||
|
url: 'https://97fca9f2-41f6-449f-a35e-3f135d4c3875.bspapp.com/http/univerify-login',
|
||||||
|
method: 'POST',
|
||||||
|
data: univerifyInfo,
|
||||||
|
success: (res) => {
|
||||||
|
const data = res.data
|
||||||
|
if (data.success) {
|
||||||
|
resolve(data.phoneNumber)
|
||||||
|
} else {
|
||||||
|
reject(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
reject(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default store
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* 这里是uni-app内置的常用样式变量
|
||||||
|
*
|
||||||
|
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||||
|
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||||
|
*
|
||||||
|
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 颜色变量 */
|
||||||
|
@import "./uni_modules/uview-ui/theme.scss";
|
||||||
|
/* 行为相关颜色 */
|
||||||
|
$uni-color-primary: #007aff;
|
||||||
|
$uni-color-success: #4cd964;
|
||||||
|
$uni-color-warning: #f0ad4e;
|
||||||
|
$uni-color-error: #dd524d;
|
||||||
|
|
||||||
|
/* 文字基本颜色 */
|
||||||
|
$uni-text-color:#333;//基本色
|
||||||
|
$uni-text-color-inverse:#fff;//反色
|
||||||
|
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||||
|
$uni-text-color-placeholder: #808080;
|
||||||
|
$uni-text-color-disable:#c0c0c0;
|
||||||
|
|
||||||
|
/* 背景颜色 */
|
||||||
|
$uni-bg-color:#ffffff;
|
||||||
|
$uni-bg-color-grey:#f8f8f8;
|
||||||
|
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||||
|
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||||
|
|
||||||
|
/* 边框颜色 */
|
||||||
|
$uni-border-color:#e5e5e5;
|
||||||
|
|
||||||
|
/* 尺寸变量 */
|
||||||
|
|
||||||
|
/* 文字尺寸 */
|
||||||
|
$uni-font-size-sm:12px;
|
||||||
|
$uni-font-size-base:14px;
|
||||||
|
$uni-font-size-lg:16;
|
||||||
|
|
||||||
|
/* 图片尺寸 */
|
||||||
|
$uni-img-size-sm:20px;
|
||||||
|
$uni-img-size-base:26px;
|
||||||
|
$uni-img-size-lg:40px;
|
||||||
|
|
||||||
|
/* Border Radius */
|
||||||
|
$uni-border-radius-sm: 2px;
|
||||||
|
$uni-border-radius-base: 3px;
|
||||||
|
$uni-border-radius-lg: 6px;
|
||||||
|
$uni-border-radius-circle: 50%;
|
||||||
|
|
||||||
|
/* 水平间距 */
|
||||||
|
$uni-spacing-row-sm: 5px;
|
||||||
|
$uni-spacing-row-base: 10px;
|
||||||
|
$uni-spacing-row-lg: 15px;
|
||||||
|
|
||||||
|
/* 垂直间距 */
|
||||||
|
$uni-spacing-col-sm: 4px;
|
||||||
|
$uni-spacing-col-base: 8px;
|
||||||
|
$uni-spacing-col-lg: 12px;
|
||||||
|
|
||||||
|
/* 透明度 */
|
||||||
|
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||||
|
|
||||||
|
/* 文章场景相关 */
|
||||||
|
$uni-color-title: #2C405A; // 文章标题颜色
|
||||||
|
$uni-font-size-title:20px;
|
||||||
|
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||||
|
$uni-font-size-subtitle:26px;
|
||||||
|
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||||
|
$uni-font-size-paragraph:15px;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
## 1.2.2(2023-01-28)
|
||||||
|
- 修复 运行/打包 控制台警告问题
|
||||||
|
## 1.2.1(2022-09-05)
|
||||||
|
- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
|
||||||
|
## 1.2.0(2021-11-19)
|
||||||
|
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||||
|
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
|
||||||
|
## 1.1.7(2021-11-08)
|
||||||
|
- 优化 升级ui
|
||||||
|
- 修改 size 属性默认值调整为 small
|
||||||
|
- 修改 type 属性,默认值调整为 error,info 替换 default
|
||||||
|
## 1.1.6(2021-09-22)
|
||||||
|
- 修复 在字节小程序上样式不生效的 bug
|
||||||
|
## 1.1.5(2021-07-30)
|
||||||
|
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||||
|
## 1.1.4(2021-07-29)
|
||||||
|
- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
|
||||||
|
## 1.1.3(2021-06-24)
|
||||||
|
- 优化 示例项目
|
||||||
|
## 1.1.1(2021-05-12)
|
||||||
|
- 新增 组件示例地址
|
||||||
|
## 1.1.0(2021-05-12)
|
||||||
|
- 新增 uni-badge 的 absolute 属性,支持定位
|
||||||
|
- 新增 uni-badge 的 offset 属性,支持定位偏移
|
||||||
|
- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
|
||||||
|
- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
|
||||||
|
- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
|
||||||
|
## 1.0.7(2021-05-07)
|
||||||
|
- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
|
||||||
|
- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
|
||||||
|
- 新增 uni-badge 属性 custom-style, 支持自定义样式
|
||||||
|
## 1.0.6(2021-02-04)
|
||||||
|
- 调整为uni_modules目录规范
|
||||||
@@ -0,0 +1,268 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-badge--x">
|
||||||
|
<slot />
|
||||||
|
<text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
|
||||||
|
class="uni-badge" @click="onClick()">{{displayValue}}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* Badge 数字角标
|
||||||
|
* @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=21
|
||||||
|
* @property {String} text 角标内容
|
||||||
|
* @property {String} size = [normal|small] 角标内容
|
||||||
|
* @property {String} type = [info|primary|success|warning|error] 颜色类型
|
||||||
|
* @value info 灰色
|
||||||
|
* @value primary 蓝色
|
||||||
|
* @value success 绿色
|
||||||
|
* @value warning 黄色
|
||||||
|
* @value error 红色
|
||||||
|
* @property {String} inverted = [true|false] 是否无需背景颜色
|
||||||
|
* @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
|
||||||
|
* @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
|
||||||
|
* @value rightTop 右上
|
||||||
|
* @value rightBottom 右下
|
||||||
|
* @value leftTop 左上
|
||||||
|
* @value leftBottom 左下
|
||||||
|
* @property {Array[number]} offset 距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
|
||||||
|
* @property {String} isDot = [true|false] 是否显示为一个小点
|
||||||
|
* @event {Function} click 点击 Badge 触发事件
|
||||||
|
* @example <uni-badge text="1"></uni-badge>
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'UniBadge',
|
||||||
|
emits: ['click'],
|
||||||
|
props: {
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'error'
|
||||||
|
},
|
||||||
|
inverted: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
isDot: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
maxNum: {
|
||||||
|
type: Number,
|
||||||
|
default: 99
|
||||||
|
},
|
||||||
|
absolute: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
offset: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return [0, 0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: 'small'
|
||||||
|
},
|
||||||
|
customStyle: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
width() {
|
||||||
|
return String(this.text).length * 8 + 12
|
||||||
|
},
|
||||||
|
classNames() {
|
||||||
|
const {
|
||||||
|
inverted,
|
||||||
|
type,
|
||||||
|
size,
|
||||||
|
absolute
|
||||||
|
} = this
|
||||||
|
return [
|
||||||
|
inverted ? 'uni-badge--' + type + '-inverted' : '',
|
||||||
|
'uni-badge--' + type,
|
||||||
|
'uni-badge--' + size,
|
||||||
|
absolute ? 'uni-badge--absolute' : ''
|
||||||
|
].join(' ')
|
||||||
|
},
|
||||||
|
positionStyle() {
|
||||||
|
if (!this.absolute) return {}
|
||||||
|
let w = this.width / 2,
|
||||||
|
h = 10
|
||||||
|
if (this.isDot) {
|
||||||
|
w = 5
|
||||||
|
h = 5
|
||||||
|
}
|
||||||
|
const x = `${- w + this.offset[0]}px`
|
||||||
|
const y = `${- h + this.offset[1]}px`
|
||||||
|
|
||||||
|
const whiteList = {
|
||||||
|
rightTop: {
|
||||||
|
right: x,
|
||||||
|
top: y
|
||||||
|
},
|
||||||
|
rightBottom: {
|
||||||
|
right: x,
|
||||||
|
bottom: y
|
||||||
|
},
|
||||||
|
leftBottom: {
|
||||||
|
left: x,
|
||||||
|
bottom: y
|
||||||
|
},
|
||||||
|
leftTop: {
|
||||||
|
left: x,
|
||||||
|
top: y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const match = whiteList[this.absolute]
|
||||||
|
return match ? match : whiteList['rightTop']
|
||||||
|
},
|
||||||
|
dotStyle() {
|
||||||
|
if (!this.isDot) return {}
|
||||||
|
return {
|
||||||
|
width: '10px',
|
||||||
|
minWidth: '0',
|
||||||
|
height: '10px',
|
||||||
|
padding: '0',
|
||||||
|
borderRadius: '10px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
displayValue() {
|
||||||
|
const {
|
||||||
|
isDot,
|
||||||
|
text,
|
||||||
|
maxNum
|
||||||
|
} = this
|
||||||
|
return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick() {
|
||||||
|
this.$emit('click');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" >
|
||||||
|
$uni-primary: #2979ff !default;
|
||||||
|
$uni-success: #4cd964 !default;
|
||||||
|
$uni-warning: #f0ad4e !default;
|
||||||
|
$uni-error: #dd524d !default;
|
||||||
|
$uni-info: #909399 !default;
|
||||||
|
|
||||||
|
|
||||||
|
$bage-size: 12px;
|
||||||
|
$bage-small: scale(0.8);
|
||||||
|
|
||||||
|
.uni-badge--x {
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
// align-self: flex-start;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: inline-block;
|
||||||
|
/* #endif */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge--absolute {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge--small {
|
||||||
|
transform: $bage-small;
|
||||||
|
transform-origin: center center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-feature-settings: "tnum";
|
||||||
|
min-width: 20px;
|
||||||
|
/* #endif */
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 20px;
|
||||||
|
padding: 0 4px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 100px;
|
||||||
|
background-color: $uni-info;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
text-align: center;
|
||||||
|
font-family: 'Helvetica Neue', Helvetica, sans-serif;
|
||||||
|
font-size: $bage-size;
|
||||||
|
/* #ifdef H5 */
|
||||||
|
z-index: 999;
|
||||||
|
cursor: pointer;
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
&--info {
|
||||||
|
color: #fff;
|
||||||
|
background-color: $uni-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--primary {
|
||||||
|
background-color: $uni-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
background-color: $uni-success;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning {
|
||||||
|
background-color: $uni-warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
background-color: $uni-error;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--inverted {
|
||||||
|
padding: 0 5px 0 0;
|
||||||
|
color: $uni-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--info-inverted {
|
||||||
|
color: $uni-info;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--primary-inverted {
|
||||||
|
color: $uni-primary;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success-inverted {
|
||||||
|
color: $uni-success;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning-inverted {
|
||||||
|
color: $uni-warning;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error-inverted {
|
||||||
|
color: $uni-error;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"id": "uni-badge",
|
||||||
|
"displayName": "uni-badge 数字角标",
|
||||||
|
"version": "1.2.2",
|
||||||
|
"description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
|
||||||
|
"keywords": [
|
||||||
|
"",
|
||||||
|
"badge",
|
||||||
|
"uni-ui",
|
||||||
|
"uniui",
|
||||||
|
"数字角标",
|
||||||
|
"徽章"
|
||||||
|
],
|
||||||
|
"repository": "https://github.com/dcloudio/uni-ui",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": ""
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"example": "../../temps/example_temps"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||||
|
"type": "component-vue"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": ["uni-scss"],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "y",
|
||||||
|
"联盟": "y"
|
||||||
|
},
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
## Badge 数字角标
|
||||||
|
> **组件名:uni-badge**
|
||||||
|
> 代码块: `uBadge`
|
||||||
|
|
||||||
|
数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
|
||||||
|
|
||||||
|
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge)
|
||||||
|
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
## 0.1.2(2022-06-08)
|
||||||
|
- 修复 微信小程序 separator 不显示问题
|
||||||
|
## 0.1.1(2022-06-02)
|
||||||
|
- 新增 支持 uni.scss 修改颜色
|
||||||
|
## 0.1.0(2022-04-21)
|
||||||
|
- 初始化
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-breadcrumb-item">
|
||||||
|
<view :class="{
|
||||||
|
'uni-breadcrumb-item--slot': true,
|
||||||
|
'uni-breadcrumb-item--slot-link': to && currentPage !== to
|
||||||
|
}" @click="navTo">
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
<i v-if="separatorClass" class="uni-breadcrumb-item--separator" :class="separatorClass" />
|
||||||
|
<text v-else class="uni-breadcrumb-item--separator">{{ separator }}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* BreadcrumbItem 面包屑导航子组件
|
||||||
|
* @property {String/Object} to 路由跳转页面路径/对象
|
||||||
|
* @property {Boolean} replace 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持)
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentPage: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
virtualHost: true
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
to: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
replace:{
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inject: {
|
||||||
|
uniBreadcrumb: {
|
||||||
|
from: "uniBreadcrumb",
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created(){
|
||||||
|
const pages = getCurrentPages()
|
||||||
|
const page = pages[pages.length-1]
|
||||||
|
|
||||||
|
if(page){
|
||||||
|
this.currentPage = `/${page.route}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
separator() {
|
||||||
|
return this.uniBreadcrumb.separator
|
||||||
|
},
|
||||||
|
separatorClass() {
|
||||||
|
return this.uniBreadcrumb.separatorClass
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
navTo() {
|
||||||
|
const { to } = this
|
||||||
|
|
||||||
|
if (!to || this.currentPage === to){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.replace){
|
||||||
|
uni.redirectTo({
|
||||||
|
url:to
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
uni.navigateTo({
|
||||||
|
url:to
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
$uni-primary: #2979ff !default;
|
||||||
|
$uni-base-color: #6a6a6a !default;
|
||||||
|
$uni-main-color: #3a3a3a !default;
|
||||||
|
.uni-breadcrumb-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&--slot {
|
||||||
|
color: $uni-base-color;
|
||||||
|
padding: 0 10px;
|
||||||
|
|
||||||
|
&-link {
|
||||||
|
color: $uni-main-color;
|
||||||
|
font-weight: bold;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
cursor: pointer;
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $uni-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--separator {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $uni-base-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child &--slot {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child &--separator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-breadcrumb">
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* Breadcrumb 面包屑导航父组件
|
||||||
|
* @description 显示当前页面的路径,快速返回之前的任意页面
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
|
||||||
|
* @property {String} separator 分隔符,默认为斜杠'/'
|
||||||
|
* @property {String} separatorClass 图标分隔符 class
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
options: {
|
||||||
|
virtualHost: true
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
separator: {
|
||||||
|
type: String,
|
||||||
|
default: '/'
|
||||||
|
},
|
||||||
|
separatorClass: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
provide() {
|
||||||
|
return {
|
||||||
|
uniBreadcrumb: this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.uni-breadcrumb {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"id": "uni-breadcrumb",
|
||||||
|
"displayName": "uni-breadcrumb 面包屑",
|
||||||
|
"version": "0.1.2",
|
||||||
|
"description": "Breadcrumb 面包屑",
|
||||||
|
"keywords": [
|
||||||
|
"uni-breadcrumb",
|
||||||
|
"breadcrumb",
|
||||||
|
"uni-ui",
|
||||||
|
"面包屑导航",
|
||||||
|
"面包屑"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"category": [
|
||||||
|
"前端组件",
|
||||||
|
"通用组件"
|
||||||
|
],
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": ""
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
},
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "n"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "u",
|
||||||
|
"百度": "u",
|
||||||
|
"字节跳动": "u",
|
||||||
|
"QQ": "u",
|
||||||
|
"京东": "u"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
## breadcrumb 面包屑导航
|
||||||
|
> **组件名:uni-breadcrumb**
|
||||||
|
> 代码块: `ubreadcrumb`
|
||||||
|
|
||||||
|
显示当前页面的路径,快速返回之前的任意页面。
|
||||||
|
|
||||||
|
### 安装方式
|
||||||
|
|
||||||
|
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
|
||||||
|
|
||||||
|
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
|
||||||
|
|
||||||
|
### 基本用法
|
||||||
|
|
||||||
|
在 ``template`` 中使用组件
|
||||||
|
|
||||||
|
```html
|
||||||
|
<uni-breadcrumb separator="/">
|
||||||
|
<uni-breadcrumb-item v-for="(route,index) in routes" :key="index" :to="route.to">{{route.name}}</uni-breadcrumb-item>
|
||||||
|
</uni-breadcrumb>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
name: "uni-stat-breadcrumb",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
routes: [{
|
||||||
|
to: '/A',
|
||||||
|
name: 'A页面'
|
||||||
|
}, {
|
||||||
|
to: '/B',
|
||||||
|
name: 'B页面'
|
||||||
|
}, {
|
||||||
|
to: '/C',
|
||||||
|
name: 'C页面'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Breadcrumb Props
|
||||||
|
|
||||||
|
|属性名 |类型 |默认值 |说明 |
|
||||||
|
|:-: |:-: |:-: |:-: |
|
||||||
|
|separator |String |斜杠'/' |分隔符 |
|
||||||
|
|separatorClass |String | |图标分隔符 class |
|
||||||
|
|
||||||
|
### Breadcrumb Item Props
|
||||||
|
|
||||||
|
|属性名 |类型 |默认值 |说明 |
|
||||||
|
|:-: |:-: |:-: |:-: |
|
||||||
|
|to |String | |路由跳转页面路径 |
|
||||||
|
|replace|Boolean | |在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 组件示例
|
||||||
|
|
||||||
|
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb](https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
## 1.4.12(2024-09-21)
|
||||||
|
- 修复 calendar在选择日期范围后重新选择日期需要点两次的Bug
|
||||||
|
## 1.4.11(2024-01-10)
|
||||||
|
- 修复 回到今天时,月份显示不一致问题
|
||||||
|
## 1.4.10(2023-04-10)
|
||||||
|
- 修复 某些情况 monthSwitch 未触发的Bug
|
||||||
|
## 1.4.9(2023-02-02)
|
||||||
|
- 修复 某些情况切换月份错误的Bug
|
||||||
|
## 1.4.8(2023-01-30)
|
||||||
|
- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964)
|
||||||
|
## 1.4.7(2022-09-16)
|
||||||
|
- 优化 支持使用 uni-scss 控制主题色
|
||||||
|
## 1.4.6(2022-09-08)
|
||||||
|
- 修复 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件的Bug
|
||||||
|
## 1.4.5(2022-02-25)
|
||||||
|
- 修复 条件编译 nvue 不支持的 css 样式的Bug
|
||||||
|
## 1.4.4(2022-02-25)
|
||||||
|
- 修复 条件编译 nvue 不支持的 css 样式的Bug
|
||||||
|
## 1.4.3(2021-09-22)
|
||||||
|
- 修复 startDate、 endDate 属性失效的Bug
|
||||||
|
## 1.4.2(2021-08-24)
|
||||||
|
- 新增 支持国际化
|
||||||
|
## 1.4.1(2021-08-05)
|
||||||
|
- 修复 弹出层被 tabbar 遮盖的Bug
|
||||||
|
## 1.4.0(2021-07-30)
|
||||||
|
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||||
|
## 1.3.16(2021-05-12)
|
||||||
|
- 新增 组件示例地址
|
||||||
|
## 1.3.15(2021-02-04)
|
||||||
|
- 调整为uni_modules目录规范
|
||||||
@@ -0,0 +1,544 @@
|
|||||||
|
/**
|
||||||
|
* @1900-2100区间内的公历、农历互转
|
||||||
|
* @charset UTF-8
|
||||||
|
* @github https://github.com/jjonline/calendar.js
|
||||||
|
* @Author Jea杨(JJonline@JJonline.Cn)
|
||||||
|
* @Time 2014-7-21
|
||||||
|
* @Time 2016-8-13 Fixed 2033hex、Attribution Annals
|
||||||
|
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
|
||||||
|
* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
|
||||||
|
* @Version 1.0.3
|
||||||
|
* @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
|
||||||
|
* @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
|
||||||
|
*/
|
||||||
|
/* eslint-disable */
|
||||||
|
var calendar = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历1900-2100的润大小信息表
|
||||||
|
* @Array Of Property
|
||||||
|
* @return Hex
|
||||||
|
*/
|
||||||
|
lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909
|
||||||
|
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
|
||||||
|
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
|
||||||
|
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
|
||||||
|
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
|
||||||
|
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
|
||||||
|
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
|
||||||
|
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
|
||||||
|
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
|
||||||
|
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
|
||||||
|
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
|
||||||
|
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
|
||||||
|
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
|
||||||
|
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
|
||||||
|
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
|
||||||
|
/** Add By JJonline@JJonline.Cn**/
|
||||||
|
0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
|
||||||
|
0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
|
||||||
|
0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
|
||||||
|
0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
|
||||||
|
0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
|
||||||
|
0x0d520], // 2100
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公历每个月份的天数普通表
|
||||||
|
* @Array Of Property
|
||||||
|
* @return Number
|
||||||
|
*/
|
||||||
|
solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天干地支之天干速查表
|
||||||
|
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天干地支之地支速查表
|
||||||
|
* @Array Of Property
|
||||||
|
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天干地支之地支速查表<=>生肖
|
||||||
|
* @Array Of Property
|
||||||
|
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 24节气速查表
|
||||||
|
* @Array Of Property
|
||||||
|
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1900-2100各年的24节气日期速查表
|
||||||
|
* @Array Of Property
|
||||||
|
* @return 0x string For splice
|
||||||
|
*/
|
||||||
|
sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
|
||||||
|
'97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||||
|
'97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
|
||||||
|
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
|
||||||
|
'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
|
||||||
|
'97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
|
||||||
|
'97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
|
||||||
|
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
|
||||||
|
'97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||||
|
'97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||||
|
'97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
|
||||||
|
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
|
||||||
|
'97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||||
|
'97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||||
|
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
|
||||||
|
'9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
|
||||||
|
'97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
|
||||||
|
'97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
|
||||||
|
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
|
||||||
|
'7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||||
|
'97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||||
|
'97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
|
||||||
|
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
|
||||||
|
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||||
|
'97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||||
|
'97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
|
||||||
|
'9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
|
||||||
|
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
|
||||||
|
'97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
|
||||||
|
'9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
|
||||||
|
'7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
|
||||||
|
'7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||||
|
'97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
|
||||||
|
'9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
|
||||||
|
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
|
||||||
|
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||||
|
'97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
|
||||||
|
'9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
|
||||||
|
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
|
||||||
|
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
|
||||||
|
'977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
|
||||||
|
'7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
|
||||||
|
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
|
||||||
|
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
|
||||||
|
'977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
|
||||||
|
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
|
||||||
|
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
|
||||||
|
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
|
||||||
|
'977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
|
||||||
|
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
|
||||||
|
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
|
||||||
|
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
|
||||||
|
'7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
|
||||||
|
'7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
|
||||||
|
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
|
||||||
|
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
|
||||||
|
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
|
||||||
|
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
|
||||||
|
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
|
||||||
|
'7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
|
||||||
|
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
|
||||||
|
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
|
||||||
|
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
|
||||||
|
'665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
|
||||||
|
'7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
|
||||||
|
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
|
||||||
|
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数字转中文速查表
|
||||||
|
* @Array Of Property
|
||||||
|
* @trans ['日','一','二','三','四','五','六','七','八','九','十']
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期转农历称呼速查表
|
||||||
|
* @Array Of Property
|
||||||
|
* @trans ['初','十','廿','卅']
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 月份转农历称呼速查表
|
||||||
|
* @Array Of Property
|
||||||
|
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回农历y年一整年的总天数
|
||||||
|
* @param lunar Year
|
||||||
|
* @return Number
|
||||||
|
* @eg:var count = calendar.lYearDays(1987) ;//count=387
|
||||||
|
*/
|
||||||
|
lYearDays: function (y) {
|
||||||
|
var i; var sum = 348
|
||||||
|
for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 }
|
||||||
|
return (sum + this.leapDays(y))
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回农历y年闰月是哪个月;若y年没有闰月 则返回0
|
||||||
|
* @param lunar Year
|
||||||
|
* @return Number (0-12)
|
||||||
|
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
|
||||||
|
*/
|
||||||
|
leapMonth: function (y) { // 闰字编码 \u95f0
|
||||||
|
return (this.lunarInfo[y - 1900] & 0xf)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回农历y年闰月的天数 若该年没有闰月则返回0
|
||||||
|
* @param lunar Year
|
||||||
|
* @return Number (0、29、30)
|
||||||
|
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
|
||||||
|
*/
|
||||||
|
leapDays: function (y) {
|
||||||
|
if (this.leapMonth(y)) {
|
||||||
|
return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
|
||||||
|
}
|
||||||
|
return (0)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法
|
||||||
|
* @param lunar Year
|
||||||
|
* @return Number (-1、29、30)
|
||||||
|
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
|
||||||
|
*/
|
||||||
|
monthDays: function (y, m) {
|
||||||
|
if (m > 12 || m < 1) { return -1 }// 月份参数从1至12,参数错误返回-1
|
||||||
|
return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回公历(!)y年m月的天数
|
||||||
|
* @param solar Year
|
||||||
|
* @return Number (-1、28、29、30、31)
|
||||||
|
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
|
||||||
|
*/
|
||||||
|
solarDays: function (y, m) {
|
||||||
|
if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
|
||||||
|
var ms = m - 1
|
||||||
|
if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29
|
||||||
|
return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28)
|
||||||
|
} else {
|
||||||
|
return (this.solarMonth[ms])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历年份转换为干支纪年
|
||||||
|
* @param lYear 农历年的年份数
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
toGanZhiYear: function (lYear) {
|
||||||
|
var ganKey = (lYear - 3) % 10
|
||||||
|
var zhiKey = (lYear - 3) % 12
|
||||||
|
if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干
|
||||||
|
if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支
|
||||||
|
return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1]
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公历月、日判断所属星座
|
||||||
|
* @param cMonth [description]
|
||||||
|
* @param cDay [description]
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
toAstro: function (cMonth, cDay) {
|
||||||
|
var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf'
|
||||||
|
var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]
|
||||||
|
return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入offset偏移量返回干支
|
||||||
|
* @param offset 相对甲子的偏移量
|
||||||
|
* @return Cn string
|
||||||
|
*/
|
||||||
|
toGanZhi: function (offset) {
|
||||||
|
return this.Gan[offset % 10] + this.Zhi[offset % 12]
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入公历(!)y年获得该年第n个节气的公历日期
|
||||||
|
* @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起
|
||||||
|
* @return day Number
|
||||||
|
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
|
||||||
|
*/
|
||||||
|
getTerm: function (y, n) {
|
||||||
|
if (y < 1900 || y > 2100) { return -1 }
|
||||||
|
if (n < 1 || n > 24) { return -1 }
|
||||||
|
var _table = this.sTermInfo[y - 1900]
|
||||||
|
var _info = [
|
||||||
|
parseInt('0x' + _table.substr(0, 5)).toString(),
|
||||||
|
parseInt('0x' + _table.substr(5, 5)).toString(),
|
||||||
|
parseInt('0x' + _table.substr(10, 5)).toString(),
|
||||||
|
parseInt('0x' + _table.substr(15, 5)).toString(),
|
||||||
|
parseInt('0x' + _table.substr(20, 5)).toString(),
|
||||||
|
parseInt('0x' + _table.substr(25, 5)).toString()
|
||||||
|
]
|
||||||
|
var _calday = [
|
||||||
|
_info[0].substr(0, 1),
|
||||||
|
_info[0].substr(1, 2),
|
||||||
|
_info[0].substr(3, 1),
|
||||||
|
_info[0].substr(4, 2),
|
||||||
|
|
||||||
|
_info[1].substr(0, 1),
|
||||||
|
_info[1].substr(1, 2),
|
||||||
|
_info[1].substr(3, 1),
|
||||||
|
_info[1].substr(4, 2),
|
||||||
|
|
||||||
|
_info[2].substr(0, 1),
|
||||||
|
_info[2].substr(1, 2),
|
||||||
|
_info[2].substr(3, 1),
|
||||||
|
_info[2].substr(4, 2),
|
||||||
|
|
||||||
|
_info[3].substr(0, 1),
|
||||||
|
_info[3].substr(1, 2),
|
||||||
|
_info[3].substr(3, 1),
|
||||||
|
_info[3].substr(4, 2),
|
||||||
|
|
||||||
|
_info[4].substr(0, 1),
|
||||||
|
_info[4].substr(1, 2),
|
||||||
|
_info[4].substr(3, 1),
|
||||||
|
_info[4].substr(4, 2),
|
||||||
|
|
||||||
|
_info[5].substr(0, 1),
|
||||||
|
_info[5].substr(1, 2),
|
||||||
|
_info[5].substr(3, 1),
|
||||||
|
_info[5].substr(4, 2)
|
||||||
|
]
|
||||||
|
return parseInt(_calday[n - 1])
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入农历数字月份返回汉语通俗表示法
|
||||||
|
* @param lunar month
|
||||||
|
* @return Cn string
|
||||||
|
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
|
||||||
|
*/
|
||||||
|
toChinaMonth: function (m) { // 月 => \u6708
|
||||||
|
if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
|
||||||
|
var s = this.nStr3[m - 1]
|
||||||
|
s += '\u6708'// 加上月字
|
||||||
|
return s
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入农历日期数字返回汉字表示法
|
||||||
|
* @param lunar day
|
||||||
|
* @return Cn string
|
||||||
|
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
|
||||||
|
*/
|
||||||
|
toChinaDay: function (d) { // 日 => \u65e5
|
||||||
|
var s
|
||||||
|
switch (d) {
|
||||||
|
case 10:
|
||||||
|
s = '\u521d\u5341'; break
|
||||||
|
case 20:
|
||||||
|
s = '\u4e8c\u5341'; break
|
||||||
|
case 30:
|
||||||
|
s = '\u4e09\u5341'; break
|
||||||
|
default :
|
||||||
|
s = this.nStr2[Math.floor(d / 10)]
|
||||||
|
s += this.nStr1[d % 10]
|
||||||
|
}
|
||||||
|
return (s)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
|
||||||
|
* @param y year
|
||||||
|
* @return Cn string
|
||||||
|
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
|
||||||
|
*/
|
||||||
|
getAnimal: function (y) {
|
||||||
|
return this.Animals[(y - 4) % 12]
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
|
||||||
|
* @param y solar year
|
||||||
|
* @param m solar month
|
||||||
|
* @param d solar day
|
||||||
|
* @return JSON object
|
||||||
|
* @eg:console.log(calendar.solar2lunar(1987,11,01));
|
||||||
|
*/
|
||||||
|
solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31
|
||||||
|
// 年份限定、上限
|
||||||
|
if (y < 1900 || y > 2100) {
|
||||||
|
return -1// undefined转换为数字变为NaN
|
||||||
|
}
|
||||||
|
// 公历传参最下限
|
||||||
|
if (y == 1900 && m == 1 && d < 31) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
// 未传参 获得当天
|
||||||
|
if (!y) {
|
||||||
|
var objDate = new Date()
|
||||||
|
} else {
|
||||||
|
var objDate = new Date(y, parseInt(m) - 1, d)
|
||||||
|
}
|
||||||
|
var i; var leap = 0; var temp = 0
|
||||||
|
// 修正ymd参数
|
||||||
|
var y = objDate.getFullYear()
|
||||||
|
var m = objDate.getMonth() + 1
|
||||||
|
var d = objDate.getDate()
|
||||||
|
var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000
|
||||||
|
for (i = 1900; i < 2101 && offset > 0; i++) {
|
||||||
|
temp = this.lYearDays(i)
|
||||||
|
offset -= temp
|
||||||
|
}
|
||||||
|
if (offset < 0) {
|
||||||
|
offset += temp; i--
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否今天
|
||||||
|
var isTodayObj = new Date()
|
||||||
|
var isToday = false
|
||||||
|
if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
|
||||||
|
isToday = true
|
||||||
|
}
|
||||||
|
// 星期几
|
||||||
|
var nWeek = objDate.getDay()
|
||||||
|
var cWeek = this.nStr1[nWeek]
|
||||||
|
// 数字表示周几顺应天朝周一开始的惯例
|
||||||
|
if (nWeek == 0) {
|
||||||
|
nWeek = 7
|
||||||
|
}
|
||||||
|
// 农历年
|
||||||
|
var year = i
|
||||||
|
var leap = this.leapMonth(i) // 闰哪个月
|
||||||
|
var isLeap = false
|
||||||
|
|
||||||
|
// 效验闰月
|
||||||
|
for (i = 1; i < 13 && offset > 0; i++) {
|
||||||
|
// 闰月
|
||||||
|
if (leap > 0 && i == (leap + 1) && isLeap == false) {
|
||||||
|
--i
|
||||||
|
isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数
|
||||||
|
} else {
|
||||||
|
temp = this.monthDays(year, i)// 计算农历普通月天数
|
||||||
|
}
|
||||||
|
// 解除闰月
|
||||||
|
if (isLeap == true && i == (leap + 1)) { isLeap = false }
|
||||||
|
offset -= temp
|
||||||
|
}
|
||||||
|
// 闰月导致数组下标重叠取反
|
||||||
|
if (offset == 0 && leap > 0 && i == leap + 1) {
|
||||||
|
if (isLeap) {
|
||||||
|
isLeap = false
|
||||||
|
} else {
|
||||||
|
isLeap = true; --i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (offset < 0) {
|
||||||
|
offset += temp; --i
|
||||||
|
}
|
||||||
|
// 农历月
|
||||||
|
var month = i
|
||||||
|
// 农历日
|
||||||
|
var day = offset + 1
|
||||||
|
// 天干地支处理
|
||||||
|
var sm = m - 1
|
||||||
|
var gzY = this.toGanZhiYear(year)
|
||||||
|
|
||||||
|
// 当月的两个节气
|
||||||
|
// bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
|
||||||
|
var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始
|
||||||
|
var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始
|
||||||
|
|
||||||
|
// 依据12节气修正干支月
|
||||||
|
var gzM = this.toGanZhi((y - 1900) * 12 + m + 11)
|
||||||
|
if (d >= firstNode) {
|
||||||
|
gzM = this.toGanZhi((y - 1900) * 12 + m + 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 传入的日期的节气与否
|
||||||
|
var isTerm = false
|
||||||
|
var Term = null
|
||||||
|
if (firstNode == d) {
|
||||||
|
isTerm = true
|
||||||
|
Term = this.solarTerm[m * 2 - 2]
|
||||||
|
}
|
||||||
|
if (secondNode == d) {
|
||||||
|
isTerm = true
|
||||||
|
Term = this.solarTerm[m * 2 - 1]
|
||||||
|
}
|
||||||
|
// 日柱 当月一日与 1900/1/1 相差天数
|
||||||
|
var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10
|
||||||
|
var gzD = this.toGanZhi(dayCyclical + d - 1)
|
||||||
|
// 该日期所属的星座
|
||||||
|
var astro = this.toAstro(m, d)
|
||||||
|
|
||||||
|
return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro }
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
|
||||||
|
* @param y lunar year
|
||||||
|
* @param m lunar month
|
||||||
|
* @param d lunar day
|
||||||
|
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
|
||||||
|
* @return JSON object
|
||||||
|
* @eg:console.log(calendar.lunar2solar(1987,9,10));
|
||||||
|
*/
|
||||||
|
lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1
|
||||||
|
var isLeapMonth = !!isLeapMonth
|
||||||
|
var leapOffset = 0
|
||||||
|
var leapMonth = this.leapMonth(y)
|
||||||
|
var leapDay = this.leapDays(y)
|
||||||
|
if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
|
||||||
|
if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值
|
||||||
|
var day = this.monthDays(y, m)
|
||||||
|
var _day = day
|
||||||
|
// bugFix 2016-9-25
|
||||||
|
// if month is leap, _day use leapDays method
|
||||||
|
if (isLeapMonth) {
|
||||||
|
_day = this.leapDays(y, m)
|
||||||
|
}
|
||||||
|
if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验
|
||||||
|
|
||||||
|
// 计算农历的时间差
|
||||||
|
var offset = 0
|
||||||
|
for (var i = 1900; i < y; i++) {
|
||||||
|
offset += this.lYearDays(i)
|
||||||
|
}
|
||||||
|
var leap = 0; var isAdd = false
|
||||||
|
for (var i = 1; i < m; i++) {
|
||||||
|
leap = this.leapMonth(y)
|
||||||
|
if (!isAdd) { // 处理闰月
|
||||||
|
if (leap <= i && leap > 0) {
|
||||||
|
offset += this.leapDays(y); isAdd = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset += this.monthDays(y, i)
|
||||||
|
}
|
||||||
|
// 转换闰月农历 需补充该年闰月的前一个月的时差
|
||||||
|
if (isLeapMonth) { offset += day }
|
||||||
|
// 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
|
||||||
|
var stmap = Date.UTC(1900, 1, 30, 0, 0, 0)
|
||||||
|
var calObj = new Date((offset + d - 31) * 86400000 + stmap)
|
||||||
|
var cY = calObj.getUTCFullYear()
|
||||||
|
var cM = calObj.getUTCMonth() + 1
|
||||||
|
var cD = calObj.getUTCDate()
|
||||||
|
|
||||||
|
return this.solar2lunar(cY, cM, cD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default calendar
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"uni-calender.ok": "ok",
|
||||||
|
"uni-calender.cancel": "cancel",
|
||||||
|
"uni-calender.today": "today",
|
||||||
|
"uni-calender.MON": "MON",
|
||||||
|
"uni-calender.TUE": "TUE",
|
||||||
|
"uni-calender.WED": "WED",
|
||||||
|
"uni-calender.THU": "THU",
|
||||||
|
"uni-calender.FRI": "FRI",
|
||||||
|
"uni-calender.SAT": "SAT",
|
||||||
|
"uni-calender.SUN": "SUN"
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import en from './en.json'
|
||||||
|
import zhHans from './zh-Hans.json'
|
||||||
|
import zhHant from './zh-Hant.json'
|
||||||
|
export default {
|
||||||
|
en,
|
||||||
|
'zh-Hans': zhHans,
|
||||||
|
'zh-Hant': zhHant
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"uni-calender.ok": "确定",
|
||||||
|
"uni-calender.cancel": "取消",
|
||||||
|
"uni-calender.today": "今日",
|
||||||
|
"uni-calender.SUN": "日",
|
||||||
|
"uni-calender.MON": "一",
|
||||||
|
"uni-calender.TUE": "二",
|
||||||
|
"uni-calender.WED": "三",
|
||||||
|
"uni-calender.THU": "四",
|
||||||
|
"uni-calender.FRI": "五",
|
||||||
|
"uni-calender.SAT": "六"
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"uni-calender.ok": "確定",
|
||||||
|
"uni-calender.cancel": "取消",
|
||||||
|
"uni-calender.today": "今日",
|
||||||
|
"uni-calender.SUN": "日",
|
||||||
|
"uni-calender.MON": "一",
|
||||||
|
"uni-calender.TUE": "二",
|
||||||
|
"uni-calender.WED": "三",
|
||||||
|
"uni-calender.THU": "四",
|
||||||
|
"uni-calender.FRI": "五",
|
||||||
|
"uni-calender.SAT": "六"
|
||||||
|
}
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-calendar-item__weeks-box" :class="{
|
||||||
|
'uni-calendar-item--disable':weeks.disable,
|
||||||
|
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||||
|
'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
|
||||||
|
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||||
|
'uni-calendar-item--multiple': weeks.multiple,
|
||||||
|
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||||
|
}"
|
||||||
|
@click="choiceDate(weeks)">
|
||||||
|
<view class="uni-calendar-item__weeks-box-item">
|
||||||
|
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
|
||||||
|
<text class="uni-calendar-item__weeks-box-text" :class="{
|
||||||
|
'uni-calendar-item--isDay-text': weeks.isDay,
|
||||||
|
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||||
|
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
|
||||||
|
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||||
|
'uni-calendar-item--multiple': weeks.multiple,
|
||||||
|
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||||
|
'uni-calendar-item--disable':weeks.disable,
|
||||||
|
}">{{weeks.date}}</text>
|
||||||
|
<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
|
||||||
|
'uni-calendar-item--isDay-text':weeks.isDay,
|
||||||
|
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||||
|
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
|
||||||
|
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||||
|
'uni-calendar-item--multiple': weeks.multiple,
|
||||||
|
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||||
|
}">{{todayText}}</text>
|
||||||
|
<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
|
||||||
|
'uni-calendar-item--isDay-text':weeks.isDay,
|
||||||
|
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||||
|
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
|
||||||
|
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||||
|
'uni-calendar-item--multiple': weeks.multiple,
|
||||||
|
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||||
|
'uni-calendar-item--disable':weeks.disable,
|
||||||
|
}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
|
||||||
|
<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
|
||||||
|
'uni-calendar-item--extra':weeks.extraInfo.info,
|
||||||
|
'uni-calendar-item--isDay-text':weeks.isDay,
|
||||||
|
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||||
|
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
|
||||||
|
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||||
|
'uni-calendar-item--multiple': weeks.multiple,
|
||||||
|
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||||
|
'uni-calendar-item--disable':weeks.disable,
|
||||||
|
}">{{weeks.extraInfo.info}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { initVueI18n } from '@dcloudio/uni-i18n'
|
||||||
|
import i18nMessages from './i18n/index.js'
|
||||||
|
const { t } = initVueI18n(i18nMessages)
|
||||||
|
|
||||||
|
export default {
|
||||||
|
emits:['change'],
|
||||||
|
props: {
|
||||||
|
weeks: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
calendar: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lunar: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
todayText() {
|
||||||
|
return t("uni-calender.today")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
choiceDate(weeks) {
|
||||||
|
this.$emit('change', weeks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$uni-font-size-base:14px;
|
||||||
|
$uni-text-color:#333;
|
||||||
|
$uni-font-size-sm:12px;
|
||||||
|
$uni-color-error: #e43d33;
|
||||||
|
$uni-opacity-disabled: 0.3;
|
||||||
|
$uni-text-color-disable:#c0c0c0;
|
||||||
|
$uni-primary: #2979ff !default;
|
||||||
|
.uni-calendar-item__weeks-box {
|
||||||
|
flex: 1;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item__weeks-box-text {
|
||||||
|
font-size: $uni-font-size-base;
|
||||||
|
color: $uni-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item__weeks-lunar-text {
|
||||||
|
font-size: $uni-font-size-sm;
|
||||||
|
color: $uni-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item__weeks-box-item {
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item__weeks-box-circle {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: $uni-color-error;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item--disable {
|
||||||
|
background-color: rgba(249, 249, 249, $uni-opacity-disabled);
|
||||||
|
color: $uni-text-color-disable;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item--isDay-text {
|
||||||
|
color: $uni-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item--isDay {
|
||||||
|
background-color: $uni-primary;
|
||||||
|
opacity: 0.8;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item--extra {
|
||||||
|
color: $uni-color-error;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item--checked {
|
||||||
|
background-color: $uni-primary;
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar-item--multiple {
|
||||||
|
background-color: $uni-primary;
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.uni-calendar-item--before-checked {
|
||||||
|
background-color: #ff5a5f;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.uni-calendar-item--after-checked {
|
||||||
|
background-color: #ff5a5f;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,567 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-calendar">
|
||||||
|
<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" @click="clean"></view>
|
||||||
|
<view v-if="insert || show" class="uni-calendar__content" :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}">
|
||||||
|
<view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
|
||||||
|
<view class="uni-calendar__header-btn-box" @click="close">
|
||||||
|
<text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__header-btn-box" @click="confirm">
|
||||||
|
<text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__header">
|
||||||
|
<view class="uni-calendar__header-btn-box" @click.stop="pre">
|
||||||
|
<view class="uni-calendar__header-btn uni-calendar--left"></view>
|
||||||
|
</view>
|
||||||
|
<picker mode="date" :value="date" fields="month" @change="bindDateChange">
|
||||||
|
<text class="uni-calendar__header-text">{{ (nowDate.year||'') +' / '+( nowDate.month||'')}}</text>
|
||||||
|
</picker>
|
||||||
|
<view class="uni-calendar__header-btn-box" @click.stop="next">
|
||||||
|
<view class="uni-calendar__header-btn uni-calendar--right"></view>
|
||||||
|
</view>
|
||||||
|
<text class="uni-calendar__backtoday" @click="backToday">{{todayText}}</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__box">
|
||||||
|
<view v-if="showMonth" class="uni-calendar__box-bg">
|
||||||
|
<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__weeks">
|
||||||
|
<view class="uni-calendar__weeks-day">
|
||||||
|
<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__weeks-day">
|
||||||
|
<text class="uni-calendar__weeks-day-text">{{monText}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__weeks-day">
|
||||||
|
<text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__weeks-day">
|
||||||
|
<text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__weeks-day">
|
||||||
|
<text class="uni-calendar__weeks-day-text">{{THUText}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__weeks-day">
|
||||||
|
<text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__weeks-day">
|
||||||
|
<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
|
||||||
|
<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
|
||||||
|
<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></calendar-item>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Calendar from './util.js';
|
||||||
|
import CalendarItem from './uni-calendar-item.vue'
|
||||||
|
|
||||||
|
import { initVueI18n } from '@dcloudio/uni-i18n'
|
||||||
|
import i18nMessages from './i18n/index.js'
|
||||||
|
const { t } = initVueI18n(i18nMessages)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calendar 日历
|
||||||
|
* @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=56
|
||||||
|
* @property {String} date 自定义当前时间,默认为今天
|
||||||
|
* @property {Boolean} lunar 显示农历
|
||||||
|
* @property {String} startDate 日期选择范围-开始日期
|
||||||
|
* @property {String} endDate 日期选择范围-结束日期
|
||||||
|
* @property {Boolean} range 范围选择
|
||||||
|
* @property {Boolean} insert = [true|false] 插入模式,默认为false
|
||||||
|
* @value true 弹窗模式
|
||||||
|
* @value false 插入模式
|
||||||
|
* @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
|
||||||
|
* @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
|
||||||
|
* @property {Boolean} showMonth 是否选择月份为背景
|
||||||
|
* @event {Function} change 日期改变,`insert :ture` 时生效
|
||||||
|
* @event {Function} confirm 确认选择`insert :false` 时生效
|
||||||
|
* @event {Function} monthSwitch 切换月份时触发
|
||||||
|
* @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CalendarItem
|
||||||
|
},
|
||||||
|
emits:['close','confirm','change','monthSwitch'],
|
||||||
|
props: {
|
||||||
|
date: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lunar: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
startDate: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
endDate: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
range: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
insert: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
showMonth: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
clearDate: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
weeks: [],
|
||||||
|
calendar: {},
|
||||||
|
nowDate: '',
|
||||||
|
aniMaskShow: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed:{
|
||||||
|
/**
|
||||||
|
* for i18n
|
||||||
|
*/
|
||||||
|
|
||||||
|
okText() {
|
||||||
|
return t("uni-calender.ok")
|
||||||
|
},
|
||||||
|
cancelText() {
|
||||||
|
return t("uni-calender.cancel")
|
||||||
|
},
|
||||||
|
todayText() {
|
||||||
|
return t("uni-calender.today")
|
||||||
|
},
|
||||||
|
monText() {
|
||||||
|
return t("uni-calender.MON")
|
||||||
|
},
|
||||||
|
TUEText() {
|
||||||
|
return t("uni-calender.TUE")
|
||||||
|
},
|
||||||
|
WEDText() {
|
||||||
|
return t("uni-calender.WED")
|
||||||
|
},
|
||||||
|
THUText() {
|
||||||
|
return t("uni-calender.THU")
|
||||||
|
},
|
||||||
|
FRIText() {
|
||||||
|
return t("uni-calender.FRI")
|
||||||
|
},
|
||||||
|
SATText() {
|
||||||
|
return t("uni-calender.SAT")
|
||||||
|
},
|
||||||
|
SUNText() {
|
||||||
|
return t("uni-calender.SUN")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
date(newVal) {
|
||||||
|
// this.cale.setDate(newVal)
|
||||||
|
this.init(newVal)
|
||||||
|
},
|
||||||
|
startDate(val){
|
||||||
|
this.cale.resetSatrtDate(val)
|
||||||
|
this.cale.setDate(this.nowDate.fullDate)
|
||||||
|
this.weeks = this.cale.weeks
|
||||||
|
},
|
||||||
|
endDate(val){
|
||||||
|
this.cale.resetEndDate(val)
|
||||||
|
this.cale.setDate(this.nowDate.fullDate)
|
||||||
|
this.weeks = this.cale.weeks
|
||||||
|
},
|
||||||
|
selected(newVal) {
|
||||||
|
this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
|
||||||
|
this.weeks = this.cale.weeks
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.cale = new Calendar({
|
||||||
|
selected: this.selected,
|
||||||
|
startDate: this.startDate,
|
||||||
|
endDate: this.endDate,
|
||||||
|
range: this.range,
|
||||||
|
})
|
||||||
|
this.init(this.date)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 取消穿透
|
||||||
|
clean() {},
|
||||||
|
bindDateChange(e) {
|
||||||
|
const value = e.detail.value + '-1'
|
||||||
|
this.setDate(value)
|
||||||
|
|
||||||
|
const { year,month } = this.cale.getDate(value)
|
||||||
|
this.$emit('monthSwitch', {
|
||||||
|
year,
|
||||||
|
month
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 初始化日期显示
|
||||||
|
* @param {Object} date
|
||||||
|
*/
|
||||||
|
init(date) {
|
||||||
|
this.cale.setDate(date)
|
||||||
|
this.weeks = this.cale.weeks
|
||||||
|
this.nowDate = this.calendar = this.cale.getInfo(date)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 打开日历弹窗
|
||||||
|
*/
|
||||||
|
open() {
|
||||||
|
// 弹窗模式并且清理数据
|
||||||
|
if (this.clearDate && !this.insert) {
|
||||||
|
this.cale.cleanMultipleStatus()
|
||||||
|
// this.cale.setDate(this.date)
|
||||||
|
this.init(this.date)
|
||||||
|
}
|
||||||
|
this.show = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.aniMaskShow = true
|
||||||
|
}, 50)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 关闭日历弹窗
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
this.aniMaskShow = false
|
||||||
|
this.$nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.show = false
|
||||||
|
this.$emit('close')
|
||||||
|
}, 300)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 确认按钮
|
||||||
|
*/
|
||||||
|
confirm() {
|
||||||
|
this.setEmit('confirm')
|
||||||
|
this.close()
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 变化触发
|
||||||
|
*/
|
||||||
|
change() {
|
||||||
|
if (!this.insert) return
|
||||||
|
this.setEmit('change')
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 选择月份触发
|
||||||
|
*/
|
||||||
|
monthSwitch() {
|
||||||
|
let {
|
||||||
|
year,
|
||||||
|
month
|
||||||
|
} = this.nowDate
|
||||||
|
this.$emit('monthSwitch', {
|
||||||
|
year,
|
||||||
|
month: Number(month)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 派发事件
|
||||||
|
* @param {Object} name
|
||||||
|
*/
|
||||||
|
setEmit(name) {
|
||||||
|
let {
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
date,
|
||||||
|
fullDate,
|
||||||
|
lunar,
|
||||||
|
extraInfo
|
||||||
|
} = this.calendar
|
||||||
|
this.$emit(name, {
|
||||||
|
range: this.cale.multipleStatus,
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
date,
|
||||||
|
fulldate: fullDate,
|
||||||
|
lunar,
|
||||||
|
extraInfo: extraInfo || {}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 选择天触发
|
||||||
|
* @param {Object} weeks
|
||||||
|
*/
|
||||||
|
choiceDate(weeks) {
|
||||||
|
if (weeks.disable) return
|
||||||
|
this.calendar = weeks
|
||||||
|
// 设置多选
|
||||||
|
this.cale.setMultiple(this.calendar.fullDate)
|
||||||
|
this.weeks = this.cale.weeks
|
||||||
|
this.change()
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 回到今天
|
||||||
|
*/
|
||||||
|
backToday() {
|
||||||
|
const nowYearMonth = `${this.nowDate.year}-${this.nowDate.month}`
|
||||||
|
const date = this.cale.getDate(new Date())
|
||||||
|
const todayYearMonth = `${date.year}-${date.month}`
|
||||||
|
|
||||||
|
this.init(date.fullDate)
|
||||||
|
|
||||||
|
if(nowYearMonth !== todayYearMonth) {
|
||||||
|
this.monthSwitch()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.change()
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 上个月
|
||||||
|
*/
|
||||||
|
pre() {
|
||||||
|
const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
|
||||||
|
this.setDate(preDate)
|
||||||
|
this.monthSwitch()
|
||||||
|
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 下个月
|
||||||
|
*/
|
||||||
|
next() {
|
||||||
|
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
|
||||||
|
this.setDate(nextDate)
|
||||||
|
this.monthSwitch()
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 设置日期
|
||||||
|
* @param {Object} date
|
||||||
|
*/
|
||||||
|
setDate(date) {
|
||||||
|
this.cale.setDate(date)
|
||||||
|
this.weeks = this.cale.weeks
|
||||||
|
this.nowDate = this.cale.getInfo(date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4);
|
||||||
|
$uni-border-color: #EDEDED;
|
||||||
|
$uni-text-color: #333;
|
||||||
|
$uni-bg-color-hover:#f1f1f1;
|
||||||
|
$uni-font-size-base:14px;
|
||||||
|
$uni-text-color-placeholder: #808080;
|
||||||
|
$uni-color-subtitle: #555555;
|
||||||
|
$uni-text-color-grey:#999;
|
||||||
|
.uni-calendar {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__mask {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: $uni-bg-color-mask;
|
||||||
|
transition-property: opacity;
|
||||||
|
transition-duration: 0.3s;
|
||||||
|
opacity: 0;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
z-index: 99;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar--mask-show {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar--fixed {
|
||||||
|
position: fixed;
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
bottom: 0;
|
||||||
|
/* #endif */
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
transition-property: transform;
|
||||||
|
transition-duration: 0.3s;
|
||||||
|
transform: translateY(460px);
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
bottom: calc(var(--window-bottom));
|
||||||
|
z-index: 99;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar--ani-show {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__content {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__header {
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 50px;
|
||||||
|
border-bottom-color: $uni-border-color;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar--fixed-top {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-top-color: $uni-border-color;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar--fixed-width {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__backtoday {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 25rpx;
|
||||||
|
padding: 0 5px;
|
||||||
|
padding-left: 10px;
|
||||||
|
height: 25px;
|
||||||
|
line-height: 25px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-top-left-radius: 25px;
|
||||||
|
border-bottom-left-radius: 25px;
|
||||||
|
color: $uni-text-color;
|
||||||
|
background-color: $uni-bg-color-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__header-text {
|
||||||
|
text-align: center;
|
||||||
|
width: 100px;
|
||||||
|
font-size: $uni-font-size-base;
|
||||||
|
color: $uni-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__header-btn-box {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__header-btn {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-left-color: $uni-text-color-placeholder;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-top-color: $uni-color-subtitle;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar--left {
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar--right {
|
||||||
|
transform: rotate(135deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.uni-calendar__weeks {
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__weeks-item {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__weeks-day {
|
||||||
|
flex: 1;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 45px;
|
||||||
|
border-bottom-color: #F5F5F5;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__weeks-day-text {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__box {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__box-bg {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-calendar__box-bg-text {
|
||||||
|
font-size: 200px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: $uni-text-color-grey;
|
||||||
|
opacity: 0.1;
|
||||||
|
text-align: center;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
line-height: 1;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,360 @@
|
|||||||
|
import CALENDAR from './calendar.js'
|
||||||
|
|
||||||
|
class Calendar {
|
||||||
|
constructor({
|
||||||
|
date,
|
||||||
|
selected,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
range
|
||||||
|
} = {}) {
|
||||||
|
// 当前日期
|
||||||
|
this.date = this.getDate(new Date()) // 当前初入日期
|
||||||
|
// 打点信息
|
||||||
|
this.selected = selected || [];
|
||||||
|
// 范围开始
|
||||||
|
this.startDate = startDate
|
||||||
|
// 范围结束
|
||||||
|
this.endDate = endDate
|
||||||
|
this.range = range
|
||||||
|
// 多选状态
|
||||||
|
this.cleanMultipleStatus()
|
||||||
|
// 每周日期
|
||||||
|
this.weeks = {}
|
||||||
|
// this._getWeek(this.date.fullDate)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 设置日期
|
||||||
|
* @param {Object} date
|
||||||
|
*/
|
||||||
|
setDate(date) {
|
||||||
|
this.selectDate = this.getDate(date)
|
||||||
|
this._getWeek(this.selectDate.fullDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理多选状态
|
||||||
|
*/
|
||||||
|
cleanMultipleStatus() {
|
||||||
|
this.multipleStatus = {
|
||||||
|
before: '',
|
||||||
|
after: '',
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置开始日期
|
||||||
|
*/
|
||||||
|
resetSatrtDate(startDate) {
|
||||||
|
// 范围开始
|
||||||
|
this.startDate = startDate
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置结束日期
|
||||||
|
*/
|
||||||
|
resetEndDate(endDate) {
|
||||||
|
// 范围结束
|
||||||
|
this.endDate = endDate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取任意时间
|
||||||
|
*/
|
||||||
|
getDate(date, AddDayCount = 0, str = 'day') {
|
||||||
|
if (!date) {
|
||||||
|
date = new Date()
|
||||||
|
}
|
||||||
|
if (typeof date !== 'object') {
|
||||||
|
date = date.replace(/-/g, '/')
|
||||||
|
}
|
||||||
|
const dd = new Date(date)
|
||||||
|
switch (str) {
|
||||||
|
case 'day':
|
||||||
|
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
|
||||||
|
break
|
||||||
|
case 'month':
|
||||||
|
if (dd.getDate() === 31 && AddDayCount>0) {
|
||||||
|
dd.setDate(dd.getDate() + AddDayCount)
|
||||||
|
} else {
|
||||||
|
const preMonth = dd.getMonth()
|
||||||
|
dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期
|
||||||
|
const nextMonth = dd.getMonth()
|
||||||
|
// 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
|
||||||
|
if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){
|
||||||
|
dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount))
|
||||||
|
}
|
||||||
|
// 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
|
||||||
|
if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){
|
||||||
|
dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'year':
|
||||||
|
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
|
||||||
|
break
|
||||||
|
}
|
||||||
|
const y = dd.getFullYear()
|
||||||
|
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
|
||||||
|
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
|
||||||
|
return {
|
||||||
|
fullDate: y + '-' + m + '-' + d,
|
||||||
|
year: y,
|
||||||
|
month: m,
|
||||||
|
date: d,
|
||||||
|
day: dd.getDay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上月剩余天数
|
||||||
|
*/
|
||||||
|
_getLastMonthDays(firstDay, full) {
|
||||||
|
let dateArr = []
|
||||||
|
for (let i = firstDay; i > 0; i--) {
|
||||||
|
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
|
||||||
|
dateArr.push({
|
||||||
|
date: beforeDate,
|
||||||
|
month: full.month - 1,
|
||||||
|
lunar: this.getlunar(full.year, full.month - 1, beforeDate),
|
||||||
|
disable: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return dateArr
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取本月天数
|
||||||
|
*/
|
||||||
|
_currentMonthDys(dateData, full) {
|
||||||
|
let dateArr = []
|
||||||
|
let fullDate = this.date.fullDate
|
||||||
|
for (let i = 1; i <= dateData; i++) {
|
||||||
|
let nowDate = full.year + '-' + (full.month < 10 ?
|
||||||
|
full.month : full.month) + '-' + (i < 10 ?
|
||||||
|
'0' + i : i)
|
||||||
|
// 是否今天
|
||||||
|
let isDay = fullDate === nowDate
|
||||||
|
// 获取打点信息
|
||||||
|
let info = this.selected && this.selected.find((item) => {
|
||||||
|
if (this.dateEqual(nowDate, item.date)) {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 日期禁用
|
||||||
|
let disableBefore = true
|
||||||
|
let disableAfter = true
|
||||||
|
if (this.startDate) {
|
||||||
|
// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
|
||||||
|
// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
|
||||||
|
disableBefore = this.dateCompare(this.startDate, nowDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.endDate) {
|
||||||
|
// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
|
||||||
|
// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
|
||||||
|
disableAfter = this.dateCompare(nowDate, this.endDate)
|
||||||
|
}
|
||||||
|
let multiples = this.multipleStatus.data
|
||||||
|
let checked = false
|
||||||
|
let multiplesStatus = -1
|
||||||
|
if (this.range) {
|
||||||
|
if (multiples) {
|
||||||
|
multiplesStatus = multiples.findIndex((item) => {
|
||||||
|
return this.dateEqual(item, nowDate)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (multiplesStatus !== -1) {
|
||||||
|
checked = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let data = {
|
||||||
|
fullDate: nowDate,
|
||||||
|
year: full.year,
|
||||||
|
date: i,
|
||||||
|
multiple: this.range ? checked : false,
|
||||||
|
beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
|
||||||
|
afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
|
||||||
|
month: full.month,
|
||||||
|
lunar: this.getlunar(full.year, full.month, i),
|
||||||
|
disable: !(disableBefore && disableAfter),
|
||||||
|
isDay
|
||||||
|
}
|
||||||
|
if (info) {
|
||||||
|
data.extraInfo = info
|
||||||
|
}
|
||||||
|
|
||||||
|
dateArr.push(data)
|
||||||
|
}
|
||||||
|
return dateArr
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取下月天数
|
||||||
|
*/
|
||||||
|
_getNextMonthDays(surplus, full) {
|
||||||
|
let dateArr = []
|
||||||
|
for (let i = 1; i < surplus + 1; i++) {
|
||||||
|
dateArr.push({
|
||||||
|
date: i,
|
||||||
|
month: Number(full.month) + 1,
|
||||||
|
lunar: this.getlunar(full.year, Number(full.month) + 1, i),
|
||||||
|
disable: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return dateArr
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前日期详情
|
||||||
|
* @param {Object} date
|
||||||
|
*/
|
||||||
|
getInfo(date) {
|
||||||
|
if (!date) {
|
||||||
|
date = new Date()
|
||||||
|
}
|
||||||
|
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
|
||||||
|
return dateInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较时间大小
|
||||||
|
*/
|
||||||
|
dateCompare(startDate, endDate) {
|
||||||
|
// 计算截止时间
|
||||||
|
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
|
||||||
|
// 计算详细项的截止时间
|
||||||
|
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
|
||||||
|
if (startDate <= endDate) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较时间是否相等
|
||||||
|
*/
|
||||||
|
dateEqual(before, after) {
|
||||||
|
// 计算截止时间
|
||||||
|
before = new Date(before.replace('-', '/').replace('-', '/'))
|
||||||
|
// 计算详细项的截止时间
|
||||||
|
after = new Date(after.replace('-', '/').replace('-', '/'))
|
||||||
|
if (before.getTime() - after.getTime() === 0) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日期范围内所有日期
|
||||||
|
* @param {Object} begin
|
||||||
|
* @param {Object} end
|
||||||
|
*/
|
||||||
|
geDateAll(begin, end) {
|
||||||
|
var arr = []
|
||||||
|
var ab = begin.split('-')
|
||||||
|
var ae = end.split('-')
|
||||||
|
var db = new Date()
|
||||||
|
db.setFullYear(ab[0], ab[1] - 1, ab[2])
|
||||||
|
var de = new Date()
|
||||||
|
de.setFullYear(ae[0], ae[1] - 1, ae[2])
|
||||||
|
var unixDb = db.getTime() - 24 * 60 * 60 * 1000
|
||||||
|
var unixDe = de.getTime() - 24 * 60 * 60 * 1000
|
||||||
|
for (var k = unixDb; k <= unixDe;) {
|
||||||
|
k = k + 24 * 60 * 60 * 1000
|
||||||
|
arr.push(this.getDate(new Date(parseInt(k))).fullDate)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 计算阴历日期显示
|
||||||
|
*/
|
||||||
|
getlunar(year, month, date) {
|
||||||
|
return CALENDAR.solar2lunar(year, month, date)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 设置打点
|
||||||
|
*/
|
||||||
|
setSelectInfo(data, value) {
|
||||||
|
this.selected = value
|
||||||
|
this._getWeek(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多选状态
|
||||||
|
*/
|
||||||
|
setMultiple(fullDate) {
|
||||||
|
let {
|
||||||
|
before,
|
||||||
|
after
|
||||||
|
} = this.multipleStatus
|
||||||
|
|
||||||
|
if (!this.range) return
|
||||||
|
if (before && after) {
|
||||||
|
this.multipleStatus.before = fullDate
|
||||||
|
this.multipleStatus.after = ''
|
||||||
|
this.multipleStatus.data = []
|
||||||
|
} else {
|
||||||
|
if (!before) {
|
||||||
|
this.multipleStatus.before = fullDate
|
||||||
|
} else {
|
||||||
|
this.multipleStatus.after = fullDate
|
||||||
|
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
|
||||||
|
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
|
||||||
|
} else {
|
||||||
|
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._getWeek(fullDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取每周数据
|
||||||
|
* @param {Object} dateData
|
||||||
|
*/
|
||||||
|
_getWeek(dateData) {
|
||||||
|
const {
|
||||||
|
year,
|
||||||
|
month
|
||||||
|
} = this.getDate(dateData)
|
||||||
|
let firstDay = new Date(year, month - 1, 1).getDay()
|
||||||
|
let currentDay = new Date(year, month, 0).getDate()
|
||||||
|
let dates = {
|
||||||
|
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
|
||||||
|
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
|
||||||
|
nextMonthDays: [], // 下个月开始几天
|
||||||
|
weeks: []
|
||||||
|
}
|
||||||
|
let canlender = []
|
||||||
|
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
|
||||||
|
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
|
||||||
|
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
|
||||||
|
let weeks = {}
|
||||||
|
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
|
||||||
|
for (let i = 0; i < canlender.length; i++) {
|
||||||
|
if (i % 7 === 0) {
|
||||||
|
weeks[parseInt(i / 7)] = new Array(7)
|
||||||
|
}
|
||||||
|
weeks[parseInt(i / 7)][i % 7] = canlender[i]
|
||||||
|
}
|
||||||
|
this.canlender = canlender
|
||||||
|
this.weeks = weeks
|
||||||
|
}
|
||||||
|
|
||||||
|
//静态方法
|
||||||
|
// static init(date) {
|
||||||
|
// if (!this.instance) {
|
||||||
|
// this.instance = new Calendar(date);
|
||||||
|
// }
|
||||||
|
// return this.instance;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default Calendar
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"id": "uni-calendar",
|
||||||
|
"displayName": "uni-calendar 日历",
|
||||||
|
"version": "1.4.12",
|
||||||
|
"description": "日历组件",
|
||||||
|
"keywords": [
|
||||||
|
"uni-ui",
|
||||||
|
"uniui",
|
||||||
|
"日历",
|
||||||
|
"",
|
||||||
|
"打卡",
|
||||||
|
"日历选择"
|
||||||
|
],
|
||||||
|
"repository": "https://github.com/dcloudio/uni-ui",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": ""
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"example": "../../temps/example_temps"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||||
|
"type": "component-vue"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y",
|
||||||
|
"alipay": "n"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
},
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||