From 65897d713fe067744326e9b0a6bbac98f495838c Mon Sep 17 00:00:00 2001 From: zjj <3272660260@qq.com> Date: 星期五, 16 五月 2025 14:40:22 +0800 Subject: [PATCH] #i18n --- locale/zh-Hant.json | 10 + pages/login/login.vue | 259 +++++++++++++++++++++++++++----- locale/index.js | 10 + locale/zh-Hans.json | 39 ++++ manifest.json | 2 pages/home/index.vue | 29 ++- pages.json | 4 locale/ja.json | 23 ++ main.js | 15 + locale/en.json | 36 ++++ locale/uni-app.ja.json | 36 ++++ 11 files changed, 407 insertions(+), 56 deletions(-) diff --git a/locale/en.json b/locale/en.json new file mode 100644 index 0000000..124fc38 --- /dev/null +++ b/locale/en.json @@ -0,0 +1,36 @@ +{ + "app.name": "ZoneYung WMS", + "locale.auto": "System", + "locale.en": "English", + "locale.zh-hans": "绠�浣撲腑鏂�", + "locale.zh-hant": "绻佷綋涓枃", + "locale.ja": "鏃ヨ", + "index.title": "Hello i18n", + "page.login":"Login", + "page.index":"Index", + "login":{ + "login": "login", + "loging": "loging", + "user": "user", + "pwd": "pwd", + "inputUser": "Please enter your account", + "inputPwd":"Please enter your password", + "remPwd":"remember password" + }, + "index":{ + "GR": "Goods Receipt", + "palletizing": "Palletizing", + "palletBuilding":"Pallet Building", + "inspectionRequest":"Inspection Request", + "qualityInspection":"Quality Inspection", + "defectiveMarking":"Defective Marking", + "manualPutaway":"Manual Putaway", + "stationBinding":"Station Binding", + "inboundInitiation":"Inbound Initiation", + "stationUnbinding":"Station Unbinding", + "bindAndInbound":"Binding And Inbound", + "outLogin":"Login Out" + + + } +} diff --git a/locale/index.js b/locale/index.js new file mode 100644 index 0000000..1ea674e --- /dev/null +++ b/locale/index.js @@ -0,0 +1,10 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +import ja from './ja.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant, + ja +} diff --git a/locale/ja.json b/locale/ja.json new file mode 100644 index 0000000..b2fa1b8 --- /dev/null +++ b/locale/ja.json @@ -0,0 +1,23 @@ +{ + "locale.auto": "銈枫偣銉嗐儬", + "locale.en": "鑻辫獮", + "locale.zh-hans": "绠�浣撲腑鏂�", + "locale.zh-hant": "绻佷綋涓枃", + "locale.ja": "鏃ヨ", + "index.title": "Hello i18n", + "index.home": "銉涖兗銉�", + "index.component": "銈炽兂銉濄兗銉嶃兂銉�", + "index.api": "API", + "index.schema": "Schema", + "index.demo": "uni-app globalization", + "index.demo-description": "銉︺儖銉曘儸銉笺儬銉兗銈�乵anifest.json銆乸ages.json銆併偪銉栥儛銉笺�併儦銉笺偢銆併偝銉炽儩銉笺儘銉炽儓銆丄PI銈掑惈銈併倠銆丼chema", + "index.detail": "瑭崇窗", + "index.language": "瑷�瑾�", + "index.language-info": "瑷畾", + "index.system-language": "銈枫偣銉嗐儬瑷�瑾�", + "index.application-language": "銈€儣銉偙銉笺偡銉с兂瑷�瑾�", + "index.language-change-confirm": "銇撱伄瑷畾銈掗仼鐢ㄣ仚銈嬨仺銆併偄銉椼儶銇屽啀璧峰嫊銇椼伨銇�", + "api.message": "銉°儍銈汇兗銈�", + "schema.add": "杩藉姞", + "schema.add-success": "鎴愬姛銈掕拷鍔�" +} diff --git a/locale/uni-app.ja.json b/locale/uni-app.ja.json new file mode 100644 index 0000000..41cef76 --- /dev/null +++ b/locale/uni-app.ja.json @@ -0,0 +1,36 @@ +{ + "common": { + "uni.app.quit": "銈傘亞涓�搴︽娂銇欍仺銆併偄銉椼儶銈便兗銈枫儳銉炽亴绲備簡銇椼伨銇�", + "uni.async.error": "銈点兗銉愩兗銇搞伄鎺ョ稓銇屻偪銈ゃ儬銈€偊銉堛仐銇俱仐銇熴�傜敾闈€倰銈儶銉冦偗銇椼仸鍐嶈│琛屻仐銇︺亸銇犮仌銇�", + "uni.showActionSheet.cancel": "銈儯銉炽偦銉�", + "uni.showToast.unpaired": "浣跨敤銇欍倠銇伅銆乻howToast銇╤ideToast銈掋儦銈€伀銇欍倠蹇呰銇屻亗銈嬨亾銇ㄣ伀娉ㄦ剰銇椼仸銇忋仩銇曘亜", + "uni.showLoading.unpaired": "浣跨敤銇欍倠銇伅銆乻howLoading銇╤ideLoading銈掋儦銈€伀銇欍倠蹇呰銇屻亗銈嬨亾銇ㄣ伀娉ㄦ剰銇椼仸銇忋仩銇曘亜", + "uni.showModal.cancel": "銈儯銉炽偦銉�", + "uni.showModal.confirm": "OK", + "uni.chooseImage.cancel": "銈儯銉炽偦銉�", + "uni.chooseImage.sourceType.album": "銈€儷銉愩儬銇嬨倝閬告姙", + "uni.chooseImage.sourceType.camera": "銈儭銉�", + "uni.chooseVideo.cancel": "銈儯銉炽偦銉�", + "uni.chooseVideo.sourceType.album": "銈€儷銉愩儬銇嬨倝閬告姙", + "uni.chooseVideo.sourceType.camera": "銈儭銉�", + "uni.previewImage.cancel": "銈儯銉炽偦銉�", + "uni.previewImage.button.save": "鐢诲儚銈掍繚瀛�", + "uni.previewImage.save.success": "鐢诲儚銈掋偄銉儛銉犮伀姝e父銇繚瀛樸仐銇俱仚", + "uni.previewImage.save.fail": "鐢诲儚銈掋偄銉儛銉犮伀淇濆瓨銇с亶銇俱仜銈撱仹銇椼仧", + "uni.setClipboardData.success": "銈炽兂銉嗐兂銉勩亴銈炽償銉笺仌銈屻伨銇椼仧", + "uni.scanCode.title": "銈广偔銉c兂銈炽兗銉�", + "uni.scanCode.album": "銈€儷銉愩儬", + "uni.scanCode.fail": "瑾嶈瓨銇け鏁椼仐銇俱仐銇�", + "uni.scanCode.flash.on": "銈裤儍銉併仐銇︾偣鐏�", + "uni.scanCode.flash.off": "銈裤儍銉椼仐銇﹂枆銇樸倠", + "uni.startSoterAuthentication.authContent": "鎸囩磱瑾嶈瓨...", + "uni.picker.done": "瀹屼簡", + "uni.picker.cancel": "銈儯銉炽偦銉�", + "uni.video.danmu": "銆屽季骞曘��", + "uni.video.volume": "銉溿儶銉ャ兗銉�", + "uni.button.feedback.title": "璩晱銇儠銈c兗銉夈儛銉冦偗", + "uni.button.feedback.send": "閫佷俊" + }, + "ios": {}, + "android": {} +} diff --git a/locale/zh-Hans.json b/locale/zh-Hans.json new file mode 100644 index 0000000..4d79ebe --- /dev/null +++ b/locale/zh-Hans.json @@ -0,0 +1,39 @@ +{ + "app.name": "涓壃 WMS", + "locale.auto": "绯荤粺", + "locale.en": "English", + "locale.zh-hans": "绠�浣撲腑鏂�", + "locale.zh-hant": "绻佷綋涓枃", + "locale.ja": "鏃ヨ", + "index.title": "Hello i18n", + "index.home": "涓婚〉", + "page.login":"鐧诲綍", + "page.index":"棣栭〉", + "login":{ + "login": "鐧诲綍", + "loging": "鐧诲綍涓�", + "user": "璐﹀彿", + "pwd": "瀵嗙爜", + "inputUser": "璇疯緭鍏ヨ处鍙�", + "inputPwd":"璇疯緭鍏ュ瘑鐮�", + "remPwd":"璁颁綇瀵嗙爜" + }, + "index":{ + "GR": "鍗曟嵁鏀惰揣", + "palletizing": "鍗曟嵁缁勬墭", + "palletBuilding":"缁勬墭瑙g粦", + "inspectionRequest":"鎶ユ", + "qualityInspection":"璐ㄦ", + "defectiveMarking":"涓嶈壇鏍囪", + "manualPutaway":"浜哄伐涓婃灦", + "stationBinding":"绔欑偣缁戝畾", + "inboundInitiation":"鍚姩鍏ュ簱", + "stationUnbinding":"绔欑偣瑙g粦", + "bindAndInbound":"缁戝畾&鍏ュ簱", + "outLogin":"閫�鍑虹櫥褰�" + + + } + + +} diff --git a/locale/zh-Hant.json b/locale/zh-Hant.json new file mode 100644 index 0000000..9e1a418 --- /dev/null +++ b/locale/zh-Hant.json @@ -0,0 +1,10 @@ +{ + "locale.auto": "绯荤当", + "locale.en": "English", + "locale.zh-hans": "绠�浣撲腑鏂�", + "locale.zh-hant": "绻侀珨涓枃", + "locale.ja": "鏃ヨ", + "index.title": "Hello i18n", + "index.home": "涓婚爜", + "login.login": "鐧诲綍" +} diff --git a/main.js b/main.js index 1f4d062..27d56ae 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,17 @@ import App from './App' +import messages from './locale/index' + +let i18nConfig = { + locale: uni.getLocale(),// 鑾峰彇宸茶缃殑璇█ + messages +} // #ifndef VUE3 import Vue from 'vue' +import VueI18n from 'vue-i18n' +Vue.use(VueI18n) +const i18n = new VueI18n(i18nConfig) + Vue.config.productionTip = false import '@/common/bluetooth.js'; @@ -13,6 +23,7 @@ Vue.prototype.$Mock = Mock; App.mpType = 'app' + try { function isPromise(obj) { @@ -43,6 +54,7 @@ } catch (error) { } const app = new Vue({ + i18n, ...App }) app.$mount() @@ -50,8 +62,11 @@ // #ifdef VUE3 import { createSSRApp } from 'vue' +import { createI18n } from 'vue-i18n' +const i18n = createI18n(i18nConfig) export function createApp() { const app = createSSRApp(App) + app.use(i18n) return { app } diff --git a/manifest.json b/manifest.json index 572efcc..93aef42 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { - "name" : "涓壃WMS", + "name" : "%app.name%", "appid" : "__UNI__DA5854D", "description" : "", "versionName" : "20250225A", diff --git a/pages.json b/pages.json index 737d4f7..ea09fde 100644 --- a/pages.json +++ b/pages.json @@ -3,13 +3,13 @@ { "path": "pages/login/login", "style": { - "navigationBarTitleText": "鐧� 褰�" + "navigationBarTitleText": "%page.login%" } }, { "path": "pages/home/index", "style": { - "navigationBarTitleText": "棣栭〉" + "navigationBarTitleText": "%page.index%" } }, { diff --git a/pages/home/index.vue b/pages/home/index.vue index e2c9dd2..2083db4 100644 --- a/pages/home/index.vue +++ b/pages/home/index.vue @@ -31,7 +31,7 @@ <navigator hover-class='none' url="/pages/rece/other" navigateTo> <view class="cuIcon-taoxiaopu text-blue"> </view> - <text>鍗曟嵁鏀惰揣</text> + <text>{{$t('index.GR')}}</text> </navigator> </view> @@ -46,7 +46,7 @@ <navigator hover-class='none' url="/pages/listing/matnrPalletising" navigateTo> <view class="cuIcon-cardboard text-blue"> </view> - <text>鍗曟嵁缁勬墭</text> + <text>{{$t('index.palletizing')}}</text> </navigator> </view> @@ -54,7 +54,7 @@ <navigator hover-class='none' url="/pages/listing/unPakin" navigateTo> <view class="cuIcon-cardboardforbid text-blue"> </view> - <text>缁勬墭瑙g粦</text> + <text>{{$t('index.palletBuilding')}}</text> </navigator> </view> @@ -62,7 +62,7 @@ <navigator hover-class='none' url="/pages/inspect/report" navigateTo> <view class="cuIcon-edit text-blue"> </view> - <text>鎶ユ</text> + <text>{{$t('index.inspectionRequest')}}</text> </navigator> </view> @@ -70,7 +70,7 @@ <navigator hover-class='none' url="/pages/inspect/check" navigateTo> <view class="cuIcon-warn text-blue"> </view> - <text>璐ㄦ</text> + <text>{{$t('index.qualityInspection')}}</text> </navigator> </view> @@ -78,7 +78,7 @@ <navigator hover-class='none' url="/pages/inspect/bad" navigateTo> <view class="cuIcon-appreciate text-blue"> </view> - <text>涓嶈壇鏍囪</text> + <text>{{$t('index.defectiveMarking')}}</text> </navigator> </view> @@ -87,7 +87,7 @@ <navigator hover-class='none' url="/pages/listing/labour" navigateTo> <view class="cuIcon-friendadd text-blue"> </view> - <text>浜哄伐涓婃灦</text> + <text>{{$t('index.manualPutaway')}}</text> </navigator> </view> @@ -104,28 +104,28 @@ <navigator hover-class='none' url="/pages/AGV/AGVStaBind" navigateTo> <view class="cuIcon-punch text-blue"> </view> - <text>绔欑偣缁戝畾</text> + <text>{{$t('index.stationBinding')}}</text> </navigator> </view> <view class="cu-item"> <navigator hover-class='none' url="/pages/AGV/StartInTask" navigateTo> <view class="cuIcon-punch text-blue"> </view> - <text>缁戝畾鍏ュ簱</text> + <text>{{$t('index.inboundInitiation')}}</text> </navigator> </view> <view class="cu-item"> <navigator hover-class='none' url="/pages/AGV/StaUnBind" navigateTo> <view class="cuIcon-punch text-blue"> </view> - <text>绔欑偣瑙g粦</text> + <text>{{$t('index.stationUnbinding')}}</text> </navigator> </view> <view class="cu-item"> <navigator hover-class='none' url="/pages/AGV/BindAndInTask" navigateTo> <view class="cuIcon-punch text-blue"> </view> - <text>缁戝畾&鍏ュ簱</text> + <text>{{$t('index.bindAndInbound')}}</text> </navigator> </view> @@ -149,7 +149,7 @@ </view> <view class="padding flex flex-direction"> - <view class="cu-btn bg-red margin-tb-sm lg round" @click="equit">閫�鍑虹櫥褰�</view> + <view class="cu-btn bg-red margin-tb-sm lg round" @click="equit">{{$t('index.outLogin')}}</view> </view> </view> </view> @@ -164,7 +164,10 @@ } } }, - onShow() { + + onShow() { + + this.user = uni.getStorageSync('userData'); }, methods: { diff --git a/pages/login/login.vue b/pages/login/login.vue index 7426ae2..3430788 100644 --- a/pages/login/login.vue +++ b/pages/login/login.vue @@ -1,11 +1,11 @@ <template> <view> <!-- 璁剧疆 --> - <!-- <view class="settings"> + <view class="settings"> <view class="settings-btn"> <uni-icons type="gear" size="30" color="#707070" @click="settings"></uni-icons> </view> - </view> --> + </view> <!-- logo --> <view class="logo"> <view class="logo-box"> @@ -13,14 +13,27 @@ </view> </view> <view class="content"> + <!-- 璇█閫夋嫨涓嬫媺鑿滃崟 --> + <view class="language-dropdown"> + <view class="selected-language" @click="toggleLanguageDropdown"> + <text>{{getCurrentLanguageText()}}</text> + <uni-icons type="bottom" size="14" color="#707070"></uni-icons> + </view> + <view class="language-options" v-if="showLanguageDropdown"> + <view class="language-option" v-for="(item, index) in locales" :key="index" @click="onLocaleChange(item)"> + <text>{{item.text}}</text> + <uni-icons type="checkmarkempty" size="14" color="#007AFF" v-if="item.code == applicationLocale"></uni-icons> + </view> + </view> + </view> <!-- 璐﹀彿 --> <view class="box shadow-warp"> <view class="box-icon"> <uni-icons type="person" size="20" color="#707070"></uni-icons> </view> - <view class="box-text">璐﹀彿:</view> + <view class="box-text">{{$t('login.user')}}:</view> <view class="box-input"> - <input type="text" placeholder="璇疯緭鍏ヨ处鍙�" v-model="user.userName" + <input type="text" :placeholder="$t('login.inputUser')" v-model="user.userName" placeholder-style="font-size:14px;color:#ccc;"> </view> <view class="box-show"></view> @@ -30,9 +43,9 @@ <view class="box-icon"> <uni-icons type="locked" size="20" color="#707070"></uni-icons> </view> - <view class="box-text">瀵嗙爜:</view> + <view class="box-text">{{$t('login.pwd')}}:</view> <view class="box-input"> - <input :password="!showPassword" placeholder="璇疯緭鍏ュ瘑鐮�" v-model="user.password" + <input :password="!showPassword" :placeholder="$t('login.inputPwd')" v-model="user.password" placeholder-style="font-size:14px;color:#ccc;"> </view> <view class="box-show"> @@ -45,7 +58,7 @@ <!-- 璁颁綇瀵嗙爜 --> <view class="check"> <view class="check-left"> - <view>璁颁綇瀵嗙爜</view> + <view>{{$t('login.remPwd')}}</view> </view> <view class="check-right"> <switch :checked='remberPassword' color="#FFCC33" style="zoom:.5" @change="remberChange" /> @@ -55,9 +68,9 @@ <!-- 鐧诲綍鎸夐挳 --> <view class="submit"> <view class="" style="width: 400rpx;"> - <button type="primary" @click="onLogin()" :loading="load.loading">{{load.btnText}}</button> + + <button type="primary" @click="onLogin()" :loading="loading">{{btnText}}</button> </view> - </view> <!-- 璁剧疆寮圭獥鍖哄煙 --> @@ -77,7 +90,7 @@ <view class="popup-item"> <view class="popup-item-left">椤圭洰:</view> <view class="popup-item-right"><input type="text" v-model="url.project"></view> - </view> + </view> <view class="btn"> <view class="btn-left" @click="close">鍙栨秷</view> <view class="btn-right" @click="settingConfirm">纭</view> @@ -110,7 +123,9 @@ } from '../../common/request.js' export default { data() { - return { + return { + systemLocale: '', + applicationLocale: '', version: '', showPassword: false, value: '', @@ -125,20 +140,55 @@ userName: '', password: '', }, - load: { - loading: false, - btnText: '鐧诲綍' - }, + loading: false, msgType: 'success', filename: '', dialogContent: '', elements: [], colorList: ['cyan', 'blue', 'purple', 'mauve', 'pink', 'brown', 'red', 'orange', 'yellow', 'olive', 'olive', 'grey' - ] + ], + showLanguageDropdown: false, + loginButton: 'login.login' + } + }, + computed:{ + locales() { + return [{ + text: this.$t('locale.auto'), + code: 'auto' + }, { + text: this.$t('locale.en'), + code: 'en' + }, + { + text: this.$t('locale.zh-hans'), + code: 'zh-Hans' + }, + { + text: this.$t('locale.zh-hant'), + code: 'zh-Hant' + }, + { + text: this.$t('locale.ja'), + code: 'ja' + } + ] + }, + btnText() { + return this.$t(this.loginButton); } }, onLoad() { + let systemInfo = uni.getSystemInfoSync(); + this.systemLocale = systemInfo.language; + this.applicationLocale = uni.getLocale(); + this.isAndroid = systemInfo.platform.toLowerCase() === 'android'; + uni.onLocaleChange((e) => { + this.applicationLocale = e.locale; + }) + + this.user = uni.getStorageSync('user') this.url = uni.getStorageSync('url') this.baseUrl = uni.getStorageSync('baseUrl') @@ -155,11 +205,56 @@ project: '' } } - }, + }, onShow() { this.getVersion() }, methods: { + localChange() { + console.log(this.local) + if (this.isAndroid) { + uni.showModal({ + content: this.$t('index.language-change-confirm'), + success: (res) => { + if (res.confirm) { + uni.setLocale(this.local.value); + } + } + }) + } else { + uni.setLocale(this.local.value); + this.$i18n.locale = this.local.value; + } + }, + // 鍒囨崲璇█涓嬫媺鑿滃崟鏄剧ず鐘舵�� + toggleLanguageDropdown() { + this.showLanguageDropdown = !this.showLanguageDropdown; + }, + + // 鑾峰彇褰撳墠閫夋嫨鐨勮瑷�鏂囨湰 + getCurrentLanguageText() { + const currentLocale = this.locales.find(item => item.code === this.applicationLocale); + return currentLocale ? currentLocale.text : this.$t('locale.auto'); + }, + + // 璇█閫夋嫨鏀瑰彉 + onLocaleChange(e) { + if (this.isAndroid) { + uni.showModal({ + content: this.$t('index.language-change-confirm'), + success: (res) => { + if (res.confirm) { + uni.setLocale(e.code); + this.showLanguageDropdown = false; + } + } + }) + } else { + uni.setLocale(e.code); + this.$i18n.locale = e.code; + this.showLanguageDropdown = false; + } + }, // 鏄剧ず/闅愯棌瀵嗙爜 changePassword() { this.showPassword = !this.showPassword; @@ -169,7 +264,7 @@ }, // 璁剧疆绐楀彛寮�鍚寜閽� settings() { - this.$refs.inputDialog.open() + this.$refs.inputDialog.open('') }, // 璁剧疆绐楀彛纭淇敼鎸夐挳 dialogInputConfirm() { @@ -197,8 +292,8 @@ password: this.user.password, }) if (code === 200) { - this.load.loading = true; - this.load.btnText = '鐧诲綍涓�'; + this.loading = true; + this.loginButton = 'login.loging'; uni.setStorageSync('token', data.accessToken); uni.setStorageSync('userData', data.user); if (this.remberPassword) { @@ -413,7 +508,8 @@ </script> <style> @import url('../../static/css/wms.css/wms.css'); - + + /* 璁剧疆鍖哄煙 */ .settings { min-height: 100rpx; @@ -466,8 +562,7 @@ text-align: center; } - .box-text { - width: 100rpx; + .box-text { text-align: center; } @@ -512,22 +607,6 @@ font-size: 12px; color: #909399; } - - - - - - - - - - - - - - - - /* ------ */ .shadow-warp { @@ -553,4 +632,104 @@ left: auto; transform: rotate(3deg); } -</style> \ No newline at end of file + + /* 璇█閫夋嫨涓嬫媺鑿滃崟 */ + .language-dropdown { + position: relative; + margin-bottom: 20rpx; + z-index: 10; + } + + .selected-language { + display: flex; + justify-content: space-between; + align-items: center; + padding: 15rpx 20rpx; + background-color: #f8f8f8; + border-radius: 8rpx; + border: 1px solid #e0e0e0; + } + + .language-options { + position: absolute; + top: 100%; + left: 0; + right: 0; + background-color: #ffffff; + border-radius: 8rpx; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + border: 1px solid #e0e0e0; + margin-top: 5rpx; + } + + .language-option { + display: flex; + justify-content: space-between; + align-items: center; + padding: 15rpx 20rpx; + border-bottom: 1px solid #f0f0f0; + } + + .language-option:last-child { + border-bottom: none; + } + + .language-option:active { + background-color: #f5f5f5; + } + + /* 鍏朵粬鏍峰紡 */ + .check { + width: 78%; + display: flex; + font-size: 12px; + color: #606266; + margin-top: 10rpx; + } + + .check-right { + margin-left: auto; + } + + .submit { + display: flex; + justify-content: center; + position: fixed; + width: 100%; + bottom: 100rpx; + } + + .version { + position: fixed; + width: 100%; + bottom: 0; + text-align: center; + font-size: 12px; + color: #909399; + } + /* ------ */ + + .shadow-warp { + position: relative; + box-shadow: 0 0 10upx rgba(0, 0, 0, 0.1); + } + + .shadow-warp:before, + .shadow-warp:after { + position: absolute; + content: ""; + top: 20upx; + bottom: 30upx; + left: 20upx; + width: 50%; + box-shadow: 0 30upx 20upx rgba(0, 0, 0, 0.2); + transform: rotate(-3deg); + z-index: -1; + } + + .shadow-warp:after { + right: 20upx; + left: auto; + transform: rotate(3deg); + } +</style> -- Gitblit v1.9.1