feat: login rest
@@ -2,39 +2,72 @@ import request from './utils/request';
|
|||||||
|
|
||||||
App({
|
App({
|
||||||
onLaunch() {
|
onLaunch() {
|
||||||
// Login
|
// Initialize login process immediately
|
||||||
|
this.loginPromise = new Promise((resolve, reject) => {
|
||||||
|
this._resolveLogin = resolve;
|
||||||
|
this._rejectLogin = reject;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.doLogin();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Perform actual login
|
||||||
|
doLogin() {
|
||||||
wx.login({
|
wx.login({
|
||||||
success: res => {
|
success: res => {
|
||||||
// Send res.code to backend to swap for openId, sessionKey, unionId
|
|
||||||
if (res.code) {
|
if (res.code) {
|
||||||
request.get('/auth/miniLogin', { code: res.code }).then(data => {
|
request.get('/auth/miniLogin', { code: res.code }).then(async (data) => {
|
||||||
// Response structure based on user input: { user: {...}, token: "...", expiresAt: ... }
|
|
||||||
// Note: request.js might return data.user directly if it unwraps 'data'
|
|
||||||
// But looking at previous request.js usage, it seems to return the 'data' field of the response.
|
|
||||||
// Let's handle both cases safely.
|
|
||||||
|
|
||||||
const token = data.token;
|
const token = data.token;
|
||||||
const user = data.user;
|
|
||||||
|
|
||||||
if (token && typeof token === 'string') {
|
if (token && typeof token === 'string') {
|
||||||
wx.setStorageSync('token', token);
|
wx.setStorageSync('token', token);
|
||||||
if (user) {
|
console.log('Login successful');
|
||||||
wx.setStorageSync('userInfo', user);
|
if (this._resolveLogin) this._resolveLogin(token);
|
||||||
this.globalData.userInfo = user;
|
|
||||||
|
// Background Profile Update
|
||||||
|
request.get('/profile/detail').then(userDetail => {
|
||||||
|
if (userDetail) {
|
||||||
|
wx.setStorageSync('userInfo', userDetail);
|
||||||
|
this.globalData.userInfo = userDetail;
|
||||||
}
|
}
|
||||||
console.log('Login successful, user info stored');
|
}).catch(e => {
|
||||||
|
console.error('Fetch profile detail failed on launch', e);
|
||||||
|
// Fallback
|
||||||
|
if (data.user) {
|
||||||
|
wx.setStorageSync('userInfo', data.user);
|
||||||
|
this.globalData.userInfo = data.user;
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
console.warn('Login response did not contain a valid token', data);
|
console.warn('Login response invalid', data);
|
||||||
|
if (this._rejectLogin) this._rejectLogin('No token');
|
||||||
}
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('Login failed', err);
|
console.error('Login API failed', err);
|
||||||
|
if (this._rejectLogin) this._rejectLogin(err);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error('wx.login failed: ' + res.errMsg);
|
console.error('wx.login failed: ' + res.errMsg);
|
||||||
|
if (this._rejectLogin) this._rejectLogin(res.errMsg);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
fail: err => {
|
||||||
|
if (this._rejectLogin) this._rejectLogin(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Method for other pages/utils to wait for login
|
||||||
|
ensureLogin() {
|
||||||
|
// If token exists, resolve immediately
|
||||||
|
const token = wx.getStorageSync('token');
|
||||||
|
if (token) return Promise.resolve(token);
|
||||||
|
|
||||||
|
// Return existing promise or create new if failed previously?
|
||||||
|
// For simplicity, return the launch promise.
|
||||||
|
// In robust apps, handle token expiration and re-login here.
|
||||||
|
return this.loginPromise;
|
||||||
|
},
|
||||||
globalData: {
|
globalData: {
|
||||||
userInfo: null
|
userInfo: null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,12 @@
|
|||||||
"pages/profile/index",
|
"pages/profile/index",
|
||||||
"pages/plant-detail/edit/index",
|
"pages/plant-detail/edit/index",
|
||||||
"pages/plant-detail/index",
|
"pages/plant-detail/index",
|
||||||
|
"pages/plant-detail/growth-record/index",
|
||||||
"pages/wiki/detail/index",
|
"pages/wiki/detail/index",
|
||||||
"pages/wiki/identify/index",
|
"pages/wiki/identify/index",
|
||||||
"pages/profile/identify-history/index"
|
"pages/profile/identify-history/index",
|
||||||
|
"pages/profile/badges/index",
|
||||||
|
"pages/profile/badges/level-detail/index"
|
||||||
],
|
],
|
||||||
"window": {
|
"window": {
|
||||||
"backgroundTextStyle": "light",
|
"backgroundTextStyle": "light",
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
/** app.wxss **/
|
/** app.wxss **/
|
||||||
|
@font-face {
|
||||||
|
font-family: 't';
|
||||||
|
src: url('https://tdesign.gtimg.com/icon/0.3.1/fonts/t.woff') format('woff'),
|
||||||
|
url('https://tdesign.gtimg.com/icon/0.3.1/fonts/t.ttf') format('truetype');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
page {
|
page {
|
||||||
--primary: #558B2F;
|
--primary: #558B2F;
|
||||||
--primary-light: #9CCC65;
|
--primary-light: #9CCC65;
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 19-7-7 7-7"/><path d="M19 12H5"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 226 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 286 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="4" rx="2" ry="2"/><line x1="16" x2="16" y1="2" y2="6"/><line x1="8" x2="8" y1="2" y2="6"/><line x1="3" x2="21" y1="10" y2="10"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 346 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 304 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ccc" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 215 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ccc" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 205 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#90A4AE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 340 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#558B2F" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 340 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#FFD700" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m2 4 3 12h14l3-12-6 7-4-7-4 7-6-7zm3 16h14"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 237 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#29B6F6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 16.3c2.2 0 4-1.83 4-4.05 0-1.16-.57-2.26-1.71-3.19S7.29 6.75 7 5.3c-.29 1.45-1.14 2.8-2.29 3.76S3 11.1 3 12.25c0 2.22 1.8 4.05 4 4.05z"/><path d="M12.56 6.6A10.97 10.97 0 0 0 14 3.02c.5 2.5 2 4.9 4 6.5s3 3.5 3 5.5a6.98 6.98 0 0 1-11.91 4.97"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 438 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2196F3" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><line x1="16" x2="8" y1="13" y2="13"/><line x1="16" x2="8" y1="17" y2="17"/><line x1="10" x2="8" y1="9" y2="9"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 411 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#90A4AE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 283 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#558B2F" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 283 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 328 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 282 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 308 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#BDBDBD" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 276 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#9C27B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="7"/><polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.88"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 273 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#90A4AE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 266 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#558B2F" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 266 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#4CAF50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7V5a2 2 0 0 1 2-2h2"/><path d="M17 3h2a2 2 0 0 1 2 2v2"/><path d="M21 17v2a2 2 0 0 1-2 2h-2"/><path d="M7 21H5a2 2 0 0 1-2-2v-2"/><rect width="10" height="6" x="7" y="9" rx="2"/><path d="M7 12h10"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 393 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#8D6E63" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><line x1="20" x2="8.12" y1="4" y2="15.88"/><line x1="14.47" x2="20" y1="14.48" y2="20"/><line x1="8.12" x2="12" y1="8.12" y2="12"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 373 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" x2="16.65" y1="21" y2="16.65"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 256 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.47a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.39a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 789 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#9C27B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 238 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#78909C" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 22v-5l5-5 5 5-5 5z"/><path d="M9.5 14.5 16 8"/><path d="m17 2 5 5-.5.5a3.53 3.53 0 0 1-5 0s0 0 0 0a3.53 3.53 0 0 1 0-5L17 2z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 322 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#FF9800" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 297 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#90A4AE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M12 11h4"/><path d="M12 16h4"/><path d="M8 11h.01"/><path d="M8 16h.01"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 403 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#558B2F" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M12 11h4"/><path d="M12 16h4"/><path d="M8 11h.01"/><path d="M8 16h.01"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 403 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#FFD700" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"/><path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"/><path d="M18 2H6v7a6 6 0 0 0 12 0V2Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 465 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#90A4AE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 289 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#558B2F" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 289 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 224 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2196F3" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 241 B |
@@ -5,9 +5,9 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"node_modules/tdesign-miniprogram": {
|
"node_modules/tdesign-miniprogram": {
|
||||||
"version": "1.12.2",
|
"version": "1.12.3",
|
||||||
"resolved": "https://registry.npmjs.org/tdesign-miniprogram/-/tdesign-miniprogram-1.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/tdesign-miniprogram/-/tdesign-miniprogram-1.12.3.tgz",
|
||||||
"integrity": "sha512-ZpOdwonT26RRCK/FWbg9tR2lAJ54Hb4PAdyTWu8URWkbKOmSQhn0JCwCtWWRofKbyWCPsCn5NqljobaGh5VCMg==",
|
"integrity": "sha512-F4nMv/ph3yyq9bO4RrJuB9x9VWyKIN6lV1HqFaV4AsR0cpDoBYtGYLPOFejvj0MYDSntSHLMVe1nm0fqsXUaUQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,21 @@ toc: false
|
|||||||
docClass: timeline
|
docClass: timeline
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 🌈 1.12.3 `2026-02-03`
|
||||||
|
|
||||||
|
### 🚀 Features
|
||||||
|
|
||||||
|
- `ActionSheet`: 为 `items` 子项的 `icon` 字段新增 `object` 类型,支持透传到 `TIcon` 组件 @anlyyao ([#4251](https://github.com/Tencent/tdesign-miniprogram/pull/4251))
|
||||||
|
- `Button`: 新增 `activity-type`,`entrance-path` 和 `need-show-entrance` 属性 @anlyyao ([#4220](https://github.com/Tencent/tdesign-miniprogram/pull/4220))
|
||||||
|
- `ChatActionbar`: 支持长按展示 @mimaoxiao ([#4071](https://github.com/Tencent/tdesign-miniprogram/pull/4071))
|
||||||
|
- `Icon`: 新增 217 个与人工智能、文档、徽标和文件相关的图标 @uyarn ([#4207](https://github.com/Tencent/tdesign-miniprogram/pull/4207))
|
||||||
|
- `Search`: 为 `change` 事件新增 `trigger` 参数,表示触发源 @anlyyao ([#4223](https://github.com/Tencent/tdesign-miniprogram/pull/4223))
|
||||||
|
|
||||||
|
### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- `ChatContent`: 修复英文单词在换行时被截断的问题 @mimaoxiao ([#4226](https://github.com/Tencent/tdesign-miniprogram/pull/4226))
|
||||||
|
- `Popup`: 修复 `duration` 参数无效的问题 @novlan1 ([#4201](https://github.com/Tencent/tdesign-miniprogram/pull/4201))
|
||||||
|
|
||||||
## 🌈 1.12.2 `2026-01-21`
|
## 🌈 1.12.2 `2026-01-21`
|
||||||
|
|
||||||
### 🚀 Features
|
### 🚀 Features
|
||||||
|
|||||||
@@ -1,22 +1,7 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
export default class ActionSheet extends SuperComponent {
|
export default class ActionSheet extends SuperComponent {
|
||||||
static show: (options: import("./show").ActionSheetShowOption) => WechatMiniprogram.Component.TrivialInstance;
|
static show: (options: import("./show").ActionSheetShowOption) => WechatMiniprogram.Component.TrivialInstance;
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>[];
|
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
properties: {
|
properties: {
|
||||||
align?: {
|
align?: {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<wxs src="./action-sheet.wxs" module="_this"/><wxs src="../common/utils.wxs" module="_"/><import src="./template/list.wxml"/><import src="./template/grid.wxml"/><view id="{{classPrefix}}" style="{{_._style([style, customStyle])}}" class="{{_.cls(classPrefix, [align, theme, ['no-description', !description]])}} class {{prefix}}-class"><t-popup visible="{{visible}}" placement="bottom" usingCustomNavbar="{{usingCustomNavbar}}" bind:visible-change="onPopupVisibleChange" show-overlay="{{showOverlay}}" z-index="{{ popupProps.zIndex || defaultPopUpzIndex }}" overlay-props="{{ popupProps.overlayProps || defaultPopUpProps }}"><view class="{{classPrefix}}__content {{prefix}}-class-content" tabindex="0"><view wx:if="{{description}}" tabindex="0" class="{{classPrefix}}__description">{{description}}</view><block wx:if="{{gridThemeItems.length}}"><template is="grid" data="{{classPrefix, prefix, gridThemeItems, count, currentSwiperIndex}}"/></block><view wx:elif="{{items && items.length}}" class="{{classPrefix}}__list"><block wx:for="{{ items }}" wx:key="index"><template is="list" data="{{index, classPrefix, listThemeItemClass: _.cls(classPrefix + '__list-item', [['disabled', item.disabled]]), item}}"/></block></view></view><slot/><view wx:if="{{showCancel}}" class="{{classPrefix}}__footer"><view class="{{classPrefix}}__gap-{{theme}}"/><view class="{{classPrefix}}__cancel {{prefix}}-class-cancel" hover-class="{{classPrefix}}__cancel--hover" hover-stay-time="70" bind:tap="onCancel" aria-role="button">{{ cancelText || '取消' }}</view></view></t-popup></view>
|
<wxs src="./action-sheet.wxs" module="_this"/><wxs src="../common/utils.wxs" module="_"/><import src="./template/grid.wxml"/><import src="../common/template/icon.wxml"/><view id="{{classPrefix}}" style="{{_._style([style, customStyle])}}" class="{{_.cls(classPrefix, [align, theme, ['no-description', !description]])}} class {{prefix}}-class"><t-popup visible="{{visible}}" placement="bottom" usingCustomNavbar="{{usingCustomNavbar}}" bind:visible-change="onPopupVisibleChange" show-overlay="{{showOverlay}}" z-index="{{ popupProps.zIndex || defaultPopUpzIndex }}" overlay-props="{{ popupProps.overlayProps || defaultPopUpProps }}"><view class="{{classPrefix}}__content {{prefix}}-class-content" tabindex="0"><view wx:if="{{description}}" tabindex="0" class="{{classPrefix}}__description">{{description}}</view><block wx:if="{{gridThemeItems.length}}"><template is="grid" data="{{classPrefix, prefix, gridThemeItems, count, currentSwiperIndex}}"/></block><view wx:elif="{{items && items.length}}" class="{{classPrefix}}__list"><block wx:for="{{ items }}" wx:key="index"><view data-index="{{index}}" style="{{ item.color ? 'color: ' + item.color : '' }}" class="{{_.cls(classPrefix + '__list-item', [['disabled', item.disabled]])}}" bind:tap="onSelect" aria-role="{{ariaRole || 'button'}}" aria-label="{{item.label || item}}" tabindex="0"><view class="{{classPrefix}}__list-item-content"><template wx:if="{{_this.getIconData(item.icon)}}" is="icon" data="{{tClass: classPrefix + '__list-item-icon', ..._this.getIconData(item.icon)}}"/><view class="{{classPrefix}}__list-item-text">{{item.label || item}}</view><template wx:if="{{_this.getIconData(item.suffixIcon)}}" is="icon" data="{{tClass: classPrefix + '__list-item-icon--suffix', ..._this.getIconData(item.suffixIcon)}}"/></view><view wx:if="{{item.description}}" class="{{classPrefix}}__list-item-desc">{{item.description}}</view></view></block></view></view><slot/><view wx:if="{{showCancel}}" class="{{classPrefix}}__footer"><view class="{{classPrefix}}__gap-{{theme}}"/><view class="{{classPrefix}}__cancel {{prefix}}-class-cancel" hover-class="{{classPrefix}}__cancel--hover" hover-stay-time="70" bind:tap="onCancel" aria-role="button">{{ cancelText || '取消' }}</view></view></t-popup></view>
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var utils = require('../common/utils.wxs');
|
||||||
|
|
||||||
var getListThemeItemClass = function (props) {
|
var getListThemeItemClass = function (props) {
|
||||||
var classPrefix = props.classPrefix;
|
var classPrefix = props.classPrefix;
|
||||||
var item = props.item;
|
var item = props.item;
|
||||||
@@ -9,11 +11,24 @@ var getListThemeItemClass = function (props) {
|
|||||||
return classList.join(' ');
|
return classList.join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var getIconData = function (icon) {
|
||||||
|
if (utils.isString(icon)) {
|
||||||
|
return { name: icon };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utils.isNoEmptyObj(icon)) {
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
var isImage = function (name) {
|
var isImage = function (name) {
|
||||||
return name.indexOf('/') !== -1;
|
return name.indexOf('/') !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getListThemeItemClass: getListThemeItemClass,
|
getListThemeItemClass: getListThemeItemClass,
|
||||||
|
getIconData: getIconData,
|
||||||
isImage: isImage,
|
isImage: isImage,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<template name="grid"><block wx:if="{{gridThemeItems.length === 1}}"><t-grid align="center" t-class="{{classPrefix}}__grid" column="{{count / 2}}" class="{{classPrefix}}__single-wrap"><t-grid-item t-class="{{classPrefix}}__grid-item" class="{{classPrefix}}__square" wx:for="{{gridThemeItems[0]}}" wx:key="index" bind:tap="onSelect" data-index="{{index}}" icon="{{ { name: item.icon, color: item.color } }}" text="{{item.label || ''}}" description="{{item.description || ''}}" image="{{item.image || ''}}" style="--td-grid-item-text-color: {{item.color}}"></t-grid-item></t-grid></block><block wx:elif="{{gridThemeItems.length > 1}}"><view class="{{classPrefix}}__swiper-wrap"><swiper style="height: 456rpx" autoplay="{{false}}" current="{{currentSwiperIndex}}" bindchange="onSwiperChange"><swiper-item wx:for="{{gridThemeItems}}" wx:key="index"><t-grid align="center" t-class="{{classPrefix}}__grid {{classPrefix}}__grid--swiper" column="{{count / 2}}"><t-grid-item t-class="{{classPrefix}}__grid-item" class="{{classPrefix}}__square" wx:for="{{item}}" wx:key="index" data-index="{{index}}" bind:tap="onSelect" icon="{{ { name: item.icon, color: item.color } }}" text="{{item.label || ''}}" description="{{item.description || ''}}" image="{{item.image || ''}}" style="--td-grid-item-text-color: {{item.color}}"></t-grid-item></t-grid></swiper-item></swiper><view class="{{classPrefix}}__nav"><view class="{{classPrefix}}__dots"><view wx:for="{{gridThemeItems.length}}" wx:key="index" class="{{classPrefix}}__dots-item {{index === currentSwiperIndex ? prefix + '-is-active' : ''}}"/></view></view></view></block></template>
|
<wxs src="../action-sheet.wxs" module="_this"/><template name="grid"><block wx:if="{{gridThemeItems.length === 1}}"><t-grid align="center" t-class="{{classPrefix}}__grid" column="{{count / 2}}" class="{{classPrefix}}__single-wrap"><t-grid-item t-class="{{classPrefix}}__grid-item" class="{{classPrefix}}__square" wx:for="{{gridThemeItems[0]}}" wx:key="index" bind:tap="onSelect" data-index="{{index}}" icon="{{ { color: item.color, ..._this.getIconData(item.icon) } }}" text="{{item.label || ''}}" description="{{item.description || ''}}" image="{{item.image || ''}}" style="--td-grid-item-text-color: {{item.color}}"></t-grid-item></t-grid></block><block wx:elif="{{gridThemeItems.length > 1}}"><view class="{{classPrefix}}__swiper-wrap"><swiper style="height: 456rpx" autoplay="{{false}}" current="{{currentSwiperIndex}}" bindchange="onSwiperChange"><swiper-item wx:for="{{gridThemeItems}}" wx:key="index"><t-grid align="center" t-class="{{classPrefix}}__grid {{classPrefix}}__grid--swiper" column="{{count / 2}}"><t-grid-item t-class="{{classPrefix}}__grid-item" class="{{classPrefix}}__square" wx:for="{{item}}" wx:key="index" data-index="{{index}}" bind:tap="onSelect" icon="{{ { color: item.color, ..._this.getIconData(item.icon) } }}" text="{{item.label || ''}}" description="{{item.description || ''}}" image="{{item.image || ''}}" style="--td-grid-item-text-color: {{item.color}}"></t-grid-item></t-grid></swiper-item></swiper><view class="{{classPrefix}}__nav"><view class="{{classPrefix}}__dots"><view wx:for="{{gridThemeItems.length}}" wx:key="index" class="{{classPrefix}}__dots-item {{index === currentSwiperIndex ? prefix + '-is-active' : ''}}"/></view></view></view></block></template>
|
||||||
@@ -1 +0,0 @@
|
|||||||
<template name="list"><view data-index="{{index}}" style="{{ item.color ? 'color: ' + item.color : '' }}" class="{{listThemeItemClass}}" bind:tap="onSelect" aria-role="{{ariaRole || 'button'}}" aria-label="{{item.label || item}}" tabindex="0"><view class="{{classPrefix}}__list-item-content"><t-icon wx:if="{{item.icon}}" name="{{item.icon}}" class="{{classPrefix}}__list-item-icon"/><view class="{{classPrefix}}__list-item-text">{{item.label || item}}</view><t-icon wx:if="{{item.suffixIcon}}" name="{{item.suffixIcon}}" class="{{classPrefix}}__list-item-icon {{classPrefix}}__list-item-icon--suffix"/></view><view wx:if="{{item.description}}" class="{{classPrefix}}__list-item-desc">{{item.description}}</view></view></template>
|
|
||||||
@@ -55,6 +55,6 @@ export interface ActionSheetItem {
|
|||||||
description?: string;
|
description?: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
icon?: string;
|
icon?: string | object;
|
||||||
suffixIcon?: string;
|
suffixIcon?: string | object;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<import src="../common/template/icon.wxml"/><wxs src="../common/utils.wxs" module="_"/><button id="{{tId}}" style="{{_._style([style, customStyle])}}" data-custom="{{ customDataset }}" class="class {{className}}" form-type="{{disabled || loading ? '' : type}}" open-type="{{disabled || loading ? '' : openType}}" hover-stop-propagation="{{hoverStopPropagation}}" hover-start-time="{{hoverStartTime}}" hover-stay-time="{{hoverStayTime}}" lang="{{lang}}" session-from="{{sessionFrom}}" hover-class="{{disabled || loading ? '' : (hoverClass || classPrefix + '--hover')}}" send-message-title="{{sendMessageTitle}}" send-message-path="{{sendMessagePath}}" send-message-img="{{sendMessageImg}}" app-parameter="{{appParameter}}" show-message-card="{{showMessageCard}}" catch:tap="handleTap" bind:getuserinfo="getuserinfo" bind:contact="contact" bind:createliveactivity="createliveactivity" bind:getphonenumber="getphonenumber" bind:getrealtimephonenumber="getrealtimephonenumber" bind:error="error" bind:opensetting="opensetting" bind:launchapp="launchapp" bind:chooseavatar="chooseavatar" bind:agreeprivacyauthorization="agreeprivacyauthorization" aria-label="{{ariaLabel}}"><template wx:if="{{_icon}}" is="icon" data="{{tClass: classPrefix + '__icon ' + prefix + '-class-icon', ariaHidden: true, name: iconName, ..._icon}}"/><t-loading wx:if="{{loading}}" delay="{{loadingProps.delay || 0}}" duration="{{loadingProps.duration || 800}}" indicator="{{loadingProps.indicator || true}}" inheritColor="{{loadingProps.inheritColor || true}}" layout="{{loadingProps.layout || 'horizontal'}}" pause="{{loadingProps.pause || false}}" progress="{{loadingProps.progress || 0}}" reverse="{{loadingProps.reverse || false}}" size="{{loadingProps.size || '40rpx'}}" text="{{loadingProps.text || '' }}" theme="{{loadingProps.theme || 'circular'}}" loading t-class="{{classPrefix}}__loading {{classPrefix}}__loading--wrapper" t-class-indicator="{{classPrefix}}__loading--indicator {{prefix}}-class-loading"/><view class="{{classPrefix}}__content"><slot name="content"/><block wx:if="{{content}}">{{content}}</block><slot/></view><slot name="suffix"/></button>
|
<import src="../common/template/icon.wxml"/><wxs src="../common/utils.wxs" module="_"/><button id="{{tId}}" style="{{_._style([style, customStyle])}}" data-custom="{{customDataset}}" class="class {{className}}" activity-type="{{activityType ? activityType : ''}}" entrance-path="{{entrancePath}}" form-type="{{disabled || loading ? '' : type}}" open-type="{{disabled || loading ? '' : openType}}" hover-stop-propagation="{{hoverStopPropagation}}" hover-start-time="{{hoverStartTime}}" hover-stay-time="{{hoverStayTime}}" lang="{{lang}}" need-show-entrance="{{needShowEntrance}}" session-from="{{sessionFrom}}" hover-class="{{disabled || loading ? '' : (hoverClass || classPrefix + '--hover')}}" send-message-title="{{sendMessageTitle}}" send-message-path="{{sendMessagePath}}" send-message-img="{{sendMessageImg}}" app-parameter="{{appParameter}}" show-message-card="{{showMessageCard}}" catch:tap="handleTap" bind:getuserinfo="getuserinfo" bind:contact="contact" bind:createliveactivity="createliveactivity" bind:getphonenumber="getphonenumber" bind:getrealtimephonenumber="getrealtimephonenumber" bind:error="error" bind:opensetting="opensetting" bind:launchapp="launchapp" bind:chooseavatar="chooseavatar" bind:agreeprivacyauthorization="agreeprivacyauthorization" aria-label="{{ariaLabel}}"><template wx:if="{{_icon}}" is="icon" data="{{tClass: classPrefix + '__icon ' + prefix + '-class-icon', ariaHidden: true, name: iconName, ..._icon}}"/><t-loading wx:if="{{loading}}" delay="{{loadingProps.delay || 0}}" duration="{{loadingProps.duration || 800}}" indicator="{{loadingProps.indicator || true}}" inheritColor="{{loadingProps.inheritColor || true}}" layout="{{loadingProps.layout || 'horizontal'}}" pause="{{loadingProps.pause || false}}" progress="{{loadingProps.progress || 0}}" reverse="{{loadingProps.reverse || false}}" size="{{loadingProps.size || '40rpx'}}" text="{{loadingProps.text || '' }}" theme="{{loadingProps.theme || 'circular'}}" loading t-class="{{classPrefix}}__loading {{classPrefix}}__loading--wrapper" t-class-indicator="{{classPrefix}}__loading--indicator {{prefix}}-class-loading"/><view class="{{classPrefix}}__content"><slot name="content"/><block wx:if="{{content}}">{{content}}</block><slot/></view><slot name="suffix"/></button>
|
||||||
@@ -1 +1 @@
|
|||||||
const props={appParameter:{type:String,value:""},block:{type:Boolean,value:!1},content:{type:String},customDataset:{type:null},disabled:{type:null,value:void 0},ghost:{type:Boolean,value:!1},hoverClass:{type:String,value:""},hoverStartTime:{type:Number,value:20},hoverStayTime:{type:Number,value:70},hoverStopPropagation:{type:Boolean,value:!1},icon:{type:null},lang:{type:String},loading:{type:Boolean,value:!1},loadingProps:{type:Object},openType:{type:String},phoneNumberNoQuotaToast:{type:Boolean,value:!0},sendMessageImg:{type:String,value:"截图"},sendMessagePath:{type:String,value:"当前分享路径"},sendMessageTitle:{type:String,value:"当前标题"},sessionFrom:{type:String,value:""},shape:{type:String,value:"rectangle"},showMessageCard:{type:Boolean,value:!1},size:{type:String,value:"medium"},tId:{type:String,value:""},theme:{type:String,value:"default"},type:{type:String},variant:{type:String,value:"base"}};export default props;
|
const props={activityType:{type:Number},appParameter:{type:String,value:""},block:{type:Boolean,value:!1},content:{type:String},customDataset:{type:null},disabled:{type:null,value:void 0},entrancePath:{type:String,value:""},ghost:{type:Boolean,value:!1},hoverClass:{type:String,value:""},hoverStartTime:{type:Number,value:20},hoverStayTime:{type:Number,value:70},hoverStopPropagation:{type:Boolean,value:!1},icon:{type:null},lang:{type:String},loading:{type:Boolean,value:!1},loadingProps:{type:Object},needShowEntrance:{type:Boolean,value:!0},openType:{type:String},phoneNumberNoQuotaToast:{type:Boolean,value:!0},sendMessageImg:{type:String,value:"截图"},sendMessagePath:{type:String,value:"当前分享路径"},sendMessageTitle:{type:String,value:"当前标题"},sessionFrom:{type:String,value:""},shape:{type:String,value:"rectangle"},showMessageCard:{type:Boolean,value:!1},size:{type:String,value:"medium"},tId:{type:String,value:""},theme:{type:String,value:"default"},type:{type:String},variant:{type:String,value:"base"}};export default props;
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
import { LoadingProps } from '../loading/index';
|
import { LoadingProps } from '../loading/index';
|
||||||
export interface TdButtonProps {
|
export interface TdButtonProps {
|
||||||
|
activityType?: {
|
||||||
|
type: NumberConstructor;
|
||||||
|
value?: number;
|
||||||
|
};
|
||||||
appParameter?: {
|
appParameter?: {
|
||||||
type: StringConstructor;
|
type: StringConstructor;
|
||||||
value?: string;
|
value?: string;
|
||||||
@@ -20,6 +24,10 @@ export interface TdButtonProps {
|
|||||||
type: BooleanConstructor;
|
type: BooleanConstructor;
|
||||||
value?: boolean;
|
value?: boolean;
|
||||||
};
|
};
|
||||||
|
entrancePath?: {
|
||||||
|
type: StringConstructor;
|
||||||
|
value?: string;
|
||||||
|
};
|
||||||
ghost?: {
|
ghost?: {
|
||||||
type: BooleanConstructor;
|
type: BooleanConstructor;
|
||||||
value?: boolean;
|
value?: boolean;
|
||||||
@@ -56,6 +64,10 @@ export interface TdButtonProps {
|
|||||||
type: ObjectConstructor;
|
type: ObjectConstructor;
|
||||||
value?: LoadingProps;
|
value?: LoadingProps;
|
||||||
};
|
};
|
||||||
|
needShowEntrance?: {
|
||||||
|
type: BooleanConstructor;
|
||||||
|
value?: boolean;
|
||||||
|
};
|
||||||
openType?: {
|
openType?: {
|
||||||
type: StringConstructor;
|
type: StringConstructor;
|
||||||
value?: 'contact' | 'share' | 'getPhoneNumber' | 'getUserInfo' | 'launchApp' | 'openSetting' | 'feedback' | 'chooseAvatar' | 'agreePrivacyAuthorization';
|
value?: 'contact' | 'share' | 'getPhoneNumber' | 'getUserInfo' | 'launchApp' | 'openSetting' | 'feedback' | 'chooseAvatar' | 'agreePrivacyAuthorization';
|
||||||
|
|||||||
@@ -1,24 +1,10 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
/// <reference types="miniprogram-api-typings" />
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
import { TdCalendarProps } from './type';
|
import { TdCalendarProps } from './type';
|
||||||
export interface CalendarProps extends TdCalendarProps {
|
export interface CalendarProps extends TdCalendarProps {
|
||||||
}
|
}
|
||||||
export default class Calendar extends SuperComponent {
|
export default class Calendar extends SuperComponent {
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>[];
|
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
options: WechatMiniprogram.Component.ComponentOptions;
|
options: WechatMiniprogram.Component.ComponentOptions;
|
||||||
properties: TdCalendarProps;
|
properties: TdCalendarProps;
|
||||||
|
|||||||
@@ -12,21 +12,31 @@ export default class ChatActionbar extends SuperComponent {
|
|||||||
replay: string;
|
replay: string;
|
||||||
copy: string;
|
copy: string;
|
||||||
share: string;
|
share: string;
|
||||||
|
quote: string;
|
||||||
};
|
};
|
||||||
iconActiveMap: {
|
iconActiveMap: {
|
||||||
good: string;
|
good: string;
|
||||||
bad: string;
|
bad: string;
|
||||||
};
|
};
|
||||||
|
widthStyle: string;
|
||||||
|
popoverStyle: string;
|
||||||
|
popoverPosition: string;
|
||||||
|
longpressVisible: boolean;
|
||||||
};
|
};
|
||||||
observers: {
|
observers: {
|
||||||
comment(newVal: any): void;
|
comment(newVal: any): void;
|
||||||
'actionBar, pComment'(): void;
|
'actionBar, pComment, placement'(): void;
|
||||||
|
longPressPosition(newVal: any): void;
|
||||||
};
|
};
|
||||||
methods: {
|
methods: {
|
||||||
filterSpecialChars(content: string): string;
|
filterSpecialChars(content: string): string;
|
||||||
handleActionClick(e: any): void;
|
handleActionClick(e: any): void;
|
||||||
handleCopy(): void;
|
handleCopy(): void;
|
||||||
setActions(): void;
|
setActions(): void;
|
||||||
|
setPComment(newVal: any): void;
|
||||||
|
showPopover(pos: any): void;
|
||||||
|
hidePopover(): void;
|
||||||
|
onVisibleChange(e: any): void;
|
||||||
};
|
};
|
||||||
lifetimes: {
|
lifetimes: {
|
||||||
created(): void;
|
created(): void;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";const{prefix:prefix}=config,name=`${prefix}-chat-actionbar`;let ChatActionbar=class extends SuperComponent{constructor(){super(...arguments),this.options={multipleSlots:!0},this.properties=props,this.data={actions:[],classPrefix:name,pComment:"",iconMap:{good:"thumb-up",bad:"thumb-down",replay:"refresh",copy:"copy",share:"share-1"},iconActiveMap:{good:"thumb-up-filled",bad:"thumb-down-filled"}},this.observers={comment(t){this.setData({pComment:t||""})},"actionBar, pComment"(){this.setActions()}},this.methods={filterSpecialChars(t){let e=t;const a=[];e=e.replace(/^(\s*\|.*\|.*\n\s*\|[-: ]+\|.*\n(\s*\|.*\|.*\n)*)/gm,t=>{const e=t.replace(/\[\d+(?:,\d+)*\]\(@ref\)/g,"").replace(/(\*\*|__)(.*?)\1|(\*|_)(.*?)\3/g,"$2$4").replace(/<br\s*\/?>/gi,"\n");return a.push(e),`%%TABLE${a.length-1}%%`}),e=e.replace(/^(\s*)#{1,6}\s+/gm,"$1"),e=e.replace(/(\*\*|__)(.*?)\1|(\*|_)(.*?)\3/g,"$2$4"),e=e.replace(/!\[.*?\]\(.*?\)/g,""),e=e.replace(/\[\d+(?:,\d+)*\]\(@ref\)/g,"");return e=e.replace(/(\\|`|\{|\}|\[|\]|\(|\)|\||!|@ref|\([@#]\w+\))/g,""),e=e.replace(/\[\d+\]/g,""),e=e.replace(/<br\s*\/?>/gi,"\n"),e=e.replace(/%%TABLE(\d+)%%/g,(t,e)=>a[parseInt(e,10)]||""),e.replace(/\n{3,}/g,"\n\n").trim()},handleActionClick(t){const{name:e}=t.currentTarget.dataset;if("copy"===e&&this.data.content)this.data.handleCopy();else if("good"===e){const t="good"===this.data.pComment;this.setData({pComment:t?void 0:"good"}),this.triggerEvent("actions",{name:e,active:!t})}else if("bad"===e){const t="bad"===this.data.pComment;this.setData({pComment:t?void 0:"bad"}),this.triggerEvent("actions",{name:e,active:!t})}else this.triggerEvent("actions",{name:e})},handleCopy(){if(!this.data.content)return;const t="markdown"===this.data.copyMode?this.data.content:this.data.filterSpecialChars(this.data.content);this.triggerEvent("actions",{name:"copy",data:t})},setActions(){const t=[];Array.isArray(this.properties.actionBar)&&this.properties.actionBar.forEach(e=>{"good"===e||"bad"===e?t.push({name:e,isActive:this.data.pComment===e}):t.push({name:e,isActive:!1})}),this.setData({actions:t})}},this.lifetimes={created(){this.data.filterSpecialChars=this.filterSpecialChars.bind(this),this.data.handleActionClick=this.handleActionClick.bind(this),this.data.handleCopy=this.handleCopy.bind(this)},attached(){this.setData({pComment:this.properties.comment||""}),this.setActions()},detached(){}}}};ChatActionbar=__decorate([wxComponent()],ChatActionbar);export default ChatActionbar;
|
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";const{prefix:prefix}=config,name=`${prefix}-chat-actionbar`;let ChatActionbar=class extends SuperComponent{constructor(){super(...arguments),this.options={multipleSlots:!0,styleIsolation:"shared"},this.properties=props,this.data={actions:[],classPrefix:name,pComment:"",iconMap:{good:"thumb-up",bad:"thumb-down",replay:"refresh",copy:"copy",share:"share-1",quote:"enter"},iconActiveMap:{good:"thumb-up-filled",bad:"thumb-down-filled"},widthStyle:"",popoverStyle:"transition: none;position: fixed;",popoverPosition:"",longpressVisible:!1},this.observers={comment(t){this.setPComment(t)},"actionBar, pComment, placement"(){this.setActions()},longPressPosition(t){"longpress"===this.properties.placement&&(t?this.showPopover(t):this.hidePopover())}},this.methods={filterSpecialChars(t){let e=t;const i=[];e=e.replace(/^(\s*\|.*\|.*\n\s*\|[-: ]+\|.*\n(\s*\|.*\|.*\n)*)/gm,t=>{const e=t.replace(/\[\d+(?:,\d+)*\]\(@ref\)/g,"").replace(/(\*\*|__)(.*?)\1|(\*|_)(.*?)\3/g,"$2$4").replace(/<br\s*\/?>/gi,"\n");return i.push(e),`%%TABLE${i.length-1}%%`}),e=e.replace(/^(\s*)#{1,6}\s+/gm,"$1"),e=e.replace(/(\*\*|__)(.*?)\1|(\*|_)(.*?)\3/g,"$2$4"),e=e.replace(/!\[.*?\]\(.*?\)/g,""),e=e.replace(/\[\d+(?:,\d+)*\]\(@ref\)/g,"");return e=e.replace(/(\\|`|\{|\}|\[|\]|\(|\)|\||!|@ref|\([@#]\w+\))/g,""),e=e.replace(/\[\d+\]/g,""),e=e.replace(/<br\s*\/?>/gi,"\n"),e=e.replace(/%%TABLE(\d+)%%/g,(t,e)=>i[parseInt(e,10)]||""),e.replace(/\n{3,}/g,"\n\n").trim()},handleActionClick(t){const{name:e}=t.currentTarget.dataset;if("copy"===e&&this.data.content)this.data.handleCopy();else if("good"===e){const t="good"===this.data.pComment;this.setData({pComment:t?void 0:"good"}),this.triggerEvent("actions",{name:e,active:!t,chatId:this.properties.chatId})}else if("bad"===e){const t="bad"===this.data.pComment;this.setData({pComment:t?void 0:"bad"}),this.triggerEvent("actions",{name:e,active:!t,chatId:this.properties.chatId})}else this.triggerEvent("actions",{name:e,chatId:this.properties.chatId});this.onVisibleChange({detail:{visible:!1}})},handleCopy(){if(!this.data.content)return;const t="markdown"===this.data.copyMode?this.data.content:this.data.filterSpecialChars(this.data.content);this.triggerEvent("actions",{name:"copy",data:t})},setActions(){const t={replay:"刷新",copy:"复制",good:"点赞",bad:"点踩",share:"分享",quote:"引用"},e=[];let i=[];"longpress"===this.properties.placement?i=["quote","copy","share"]:Array.isArray(this.properties.actionBar)&&(i=this.properties.actionBar),i.forEach(i=>{"good"===i||"bad"===i?e.push({name:i,isActive:this.data.pComment===i,text:t[i]||i}):e.push({name:i,isActive:!1,text:t[i]||i})}),this.setData({actions:e})},setPComment(t){this.setData({pComment:t||""})},showPopover(t){this.setData({widthStyle:`width: ${128*this.data.actions.length+8*(this.data.actions.length-1)}rpx`,popoverPosition:`top:${t.y}px;left:${t.x}px`,longpressVisible:!0}),setTimeout(()=>{const t=this.selectComponent(".popover"),e=this.createSelectorQuery().in(t);e.select(".t-popover").boundingClientRect(),e.exec(t=>{const[e]=t,{screenWidth:i}=wx.getWindowInfo();e.left+e.width>i?this.setData({popoverStyle:"transition: none;position:fixed; left: unset !important; right: 16rpx !important;"}):e.left<=0&&this.setData({popoverStyle:"transition: none;position:fixed; left: 16rpx !important;"})})},200)},hidePopover(){this.onVisibleChange({detail:{visible:!1}})},onVisibleChange(t){const{visible:e}=t.detail;this.setData({longpressVisible:e}),e||setTimeout(()=>{this.setData({popoverPosition:"",popoverStyle:"transition: none;position: fixed;"})},200)}},this.lifetimes={created(){this.data.filterSpecialChars=this.filterSpecialChars.bind(this),this.data.handleActionClick=this.handleActionClick.bind(this),this.data.handleCopy=this.handleCopy.bind(this),this.data.showPopover=this.showPopover.bind(this),this.data.hidePopover=this.hidePopover.bind(this),this.data.setPComment=this.setPComment.bind(this)},attached(){this.setData({pComment:this.properties.comment||""}),this.setActions()},detached(){}}}};ChatActionbar=__decorate([wxComponent()],ChatActionbar);export default ChatActionbar;
|
||||||
@@ -1 +1 @@
|
|||||||
{"component":true,"styleIsolation":"apply-shared","usingComponents":{"t-icon":"../icon/icon"}}
|
{"component":true,"styleIsolation":"apply-shared","usingComponents":{"t-icon":"../icon/icon","t-popover":"../popover/popover"}}
|
||||||
@@ -1 +1 @@
|
|||||||
<wxs src="../common/utils.wxs" module="_"/><view class="class {{[classPrefix, placement==='longpress' ? classPrefix+'__inner--popover' : '', computedPlacement]}}" style="{{_._style([style, customStyle])}}"><view class="{{classPrefix}}__inner {{classPrefix}}__inner--column"><view class="{{classPrefix}}__item {{classPrefix}}__left"><slot name="prefix"/></view><block wx:for="{{actions}}" wx:for-item="item" wx:for-index="index" wx:key="index"><button wx:if="{{item.name === 'share'}}" data-name="{{item.name}}" class="{{_.cls(classPrefix + '__item', [['active', item.isActive]])}}" open-type="{{content ? 'share' : 'none'}}" data-chat-id="{{chatId}}" bindtap="handleActionClick"><t-icon name="{{item.isActive ? iconActiveMap[item.name] : iconMap[item.name]}}" size="40rpx"/></button><view wx:else data-name="{{item.name}}" class="{{_.cls(classPrefix + '__item', [['active', item.isActive]])}}" bindtap="handleActionClick"><t-icon name="{{item.isActive ? iconActiveMap[item.name] : iconMap[item.name]}}" size="40rpx"/></view></block></view></view>
|
<wxs src="../common/utils.wxs" module="_"/><view wx:if="{{placement !== 'longpress'}}" class="{{[classPrefix, placement]}}" style="{{_._style([style, customStyle])}}"><view class="{{classPrefix}}__inner {{classPrefix}}__inner--column"><view class="{{classPrefix}}__left {{classPrefix+'__item'}}"><slot name="prefix"/></view><block wx:for="{{actions}}" wx:for-item="item" wx:for-index="index" wx:key="index"><button wx:if="{{item.name === 'share'}}" data-name="{{item.name}}" class="{{_.cls(classPrefix+'__item', [['active', item.isActive]])}}" open-type="{{content ? 'share' : 'none'}}" data-chat-id="{{chatId}}" bindtap="handleActionClick"><t-icon name="{{item.isActive ? iconActiveMap[item.name] : iconMap[item.name]}}" size="40rpx"/></button><view wx:else data-name="{{item.name}}" class="{{_.cls(classPrefix+'__item', [['active', item.isActive]])}}" bindtap="handleActionClick"><t-icon name="{{item.isActive ? iconActiveMap[item.name] : iconMap[item.name]}}" size="40rpx"/></view></block></view></view><view wx:else class="{{[classPrefix, classPrefix+'__popover-skeleton']}}" style="{{popoverPosition}}"><t-popover class="popover" placement="bottom" theme="dark" visible="{{longpressVisible}}" customStyle="{{popoverStyle}}" bind:visible-change="onVisibleChange"><view class="{{[classPrefix, classPrefix+'__popover-skeleton__inner']}}"></view><view slot="content" class="{{[classPrefix, classPrefix+'--popover', 'popover-visible']}}" style="{{_._style([style, customStyle, widthStyle])}}"><view class="{{classPrefix}}__inner {{classPrefix}}__inner--column"><view class="{{classPrefix}}__left {{classPrefix+'__item--popover'}}"><slot name="prefix"/></view><block wx:for="{{actions}}" wx:for-item="item" wx:for-index="index" wx:key="index"><button wx:if="{{item.name === 'share'}}" data-name="{{item.name}}" class="{{_.cls(classPrefix+'__item--popover', [['active', item.isActive]])}}" open-type="{{content ? 'share' : 'none'}}" data-chat-id="{{chatId}}" bindtap="handleActionClick"><t-icon name="{{iconMap[item.name]}}" size="40rpx"/><view class="{{classPrefix}}__item__text">{{item.text}}</view></button><view wx:else data-name="{{item.name}}" class="{{_.cls(classPrefix+'__item--popover', [['active', item.isActive]])}}" bindtap="handleActionClick"><t-icon name="{{iconMap[item.name]}}" size="40rpx" customStyle="{{item.name === 'quote' ? 'transform: scaleX(-1)' : ''}}"/><view class="{{classPrefix}}__item__text">{{item.text}}</view></view></block></view></view></t-popover></view>
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
@import '../common/style/index.wxss';.t-chat-actionbar{display:flex;padding:var(--chat-actionbar-padding,0);}
|
@import '../common/style/index.wxss';.t-chat-actionbar{display:flex;padding:var(--chat-actionbar-padding,0);}
|
||||||
.t-chat-actionbar.start{justify-content:flex-start;}
|
.t-chat-actionbar.start{justify-content:flex-start;}
|
||||||
.t-chat-actionbar.end{justify-content:flex-end;}
|
.t-chat-actionbar.end{justify-content:flex-end;}
|
||||||
|
.t-chat-actionbar--popover{color:var(--td-font-white-1,#fff);border-radius:6rpx;}
|
||||||
|
.t-chat-actionbar--popover .t-chat-actionbar__inner{background-color:unset;border:none;display:flex;flex-wrap:wrap;gap:4rpx;}
|
||||||
|
.t-chat-actionbar--popover .t-chat-actionbar__inner--column{gap:8rpx;}
|
||||||
|
.t-chat-actionbar--popover .t-chat-actionbar__item--popover{color:#fff;background-color:unset;padding:0;margin:0;font-size:28rpx;line-height:42rpx;width:128rpx;height:156rpx;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8rpx;}
|
||||||
.t-chat-actionbar__inner{background-color:var(--td-bg-color-secondarycontainer,var(--td-gray-color-1,#f3f3f3));border:2rpx solid var(--td-component-border,var(--td-gray-color-4,#dcdcdc));box-sizing:border-box;border-radius:var(--td-radius-default,12rpx);display:inline-flex;flex-direction:row;flex-wrap:nowrap;align-items:center;}
|
.t-chat-actionbar__inner{background-color:var(--td-bg-color-secondarycontainer,var(--td-gray-color-1,#f3f3f3));border:2rpx solid var(--td-component-border,var(--td-gray-color-4,#dcdcdc));box-sizing:border-box;border-radius:var(--td-radius-default,12rpx);display:inline-flex;flex-direction:row;flex-wrap:nowrap;align-items:center;}
|
||||||
.t-chat-actionbar__inner--column{display:flex;align-items:center;justify-content:space-between;}
|
.t-chat-actionbar__inner--column{display:flex;align-items:center;justify-content:space-between;}
|
||||||
.t-chat-actionbar__inner--popover{padding:45rpx;background-color:var(--td-mask-active,rgba(0,0,0,.6));border-radius:32rpx;color:var(--td-font-white-1,#fff);}
|
|
||||||
.t-chat-actionbar__left:empty{display:none;}
|
.t-chat-actionbar__left:empty{display:none;}
|
||||||
.t-chat-actionbar__item{color:var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9)));margin:12rpx 0;padding:4rpx 28rpx;border-right:2rpx solid var(--td-component-stroke,var(--td-gray-color-3,#e7e7e7));background-color:unset;outline:0;}
|
.t-chat-actionbar__item{color:var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9)));padding:var(--chat-actionbar-item-padding,16rpx 28rpx);border-right:2rpx solid var(--td-component-stroke,var(--td-gray-color-3,#e7e7e7));background-color:unset;outline:0;}
|
||||||
.t-chat-actionbar__item:after{display:none;}
|
.t-chat-actionbar__item:after{display:none;}
|
||||||
.t-chat-actionbar__item:last-child{border-right:none;}
|
.t-chat-actionbar__item:last-child{border-right:none;}
|
||||||
.t-chat-actionbar__item--active{color:var(--td-brand-color,var(--td-primary-color-7,#0052d9));}
|
.t-chat-actionbar__item--active{color:var(--td-brand-color,var(--td-primary-color-7,#0052d9));}
|
||||||
|
.t-chat-actionbar__popover-skeleton{position:fixed;--td-popover-padding:8rpx 16rpx;}
|
||||||
|
.t-chat-actionbar__popover-skeleton__inner{width:20rpx;height:20rpx;}
|
||||||
@@ -1 +1 @@
|
|||||||
const props={actionBar:{type:Array,value:["replay","copy","good","bad","share"]},chatId:{type:String,value:""},comment:{type:String,value:""},content:{type:String,value:""},copyMode:{type:String,value:"markdown"},disabled:{type:Boolean,value:!1},placement:{type:String,value:"start"}};export default props;
|
const props={actionBar:{type:Array,value:["replay","copy","good","bad","share"]},chatId:{type:String,value:""},comment:{type:String,value:""},content:{type:String,value:""},copyMode:{type:String,value:"markdown"},disabled:{type:Boolean,value:!1},placement:{type:String,value:"start"},longPressPosition:{type:Object,value:null}};export default props;
|
||||||
@@ -25,6 +25,17 @@ export interface TdChatActionbarProps {
|
|||||||
};
|
};
|
||||||
placement?: {
|
placement?: {
|
||||||
type: StringConstructor;
|
type: StringConstructor;
|
||||||
value?: 'start' | 'end' | 'space-around' | 'space-between';
|
value?: 'start' | 'end' | 'space-around' | 'space-between' | 'longpress';
|
||||||
|
};
|
||||||
|
longPressPosition?: {
|
||||||
|
type: ObjectConstructor;
|
||||||
|
value?: {
|
||||||
|
pageX: number;
|
||||||
|
pageY: number;
|
||||||
|
clientX: number;
|
||||||
|
clientY: number;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import '../common/style/index.wxss';.t-chat-content{font:var(--td-font-body-large,32rpx / 48rpx var(--td-font-family,PingFang SC,Microsoft YaHei,Arial Regular));word-break:break-all;word-wrap:break-word;overflow-wrap:break-word;box-sizing:border-box;width:fit-content;}
|
@import '../common/style/index.wxss';.t-chat-content{font:var(--td-font-body-large,32rpx / 48rpx var(--td-font-family,PingFang SC,Microsoft YaHei,Arial Regular));word-break:break-word;word-wrap:break-word;overflow-wrap:break-word;box-sizing:border-box;width:fit-content;}
|
||||||
.t-chat-content__system,.t-chat-content__user{color:var(--td-chat-content-user-text-color,var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9))));}
|
.t-chat-content__system,.t-chat-content__user{color:var(--td-chat-content-user-text-color,var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9))));}
|
||||||
.t-chat-content__system ._pre,.t-chat-content__user ._pre{margin:0;white-space:pre-wrap;}
|
.t-chat-content__system ._pre,.t-chat-content__user ._pre{margin:0;white-space:pre-wrap;}
|
||||||
.t-chat-content__assistant{color:var(--td-chat-content-assistant-text-color,var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9))));}
|
.t-chat-content__assistant{color:var(--td-chat-content-assistant-text-color,var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9))));}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import props from"./props";import config from"../common/config";const{prefix:prefix}=config,name=`${prefix}-chat-message`;let ChatMessage=class extends SuperComponent{constructor(){super(...arguments),this.options={multipleSlots:!0},this.properties=props,this.data={classPrefix:name,article:"",showAvatar:null,showName:null,showDateTime:null,contentClasses:[],chatItemClass:[]},this.observers={avatar(){this.setShowAvatar()},name(){this.setShowName()},datetime(){this.setShowDateTime()},classPrefix(){this.setContentClasses()},"classPrefix, variant, placement, showDateTime"(){this.setChatItemClass()}},this.methods={handleLongPress(t){this.triggerEvent("longpress",{e:t,id:this.data.chatId})},setShowAvatar(){var t;this.setData({showAvatar:(null===(t=this.properties)||void 0===t?void 0:t.avatar)||""})},setShowName(){var t;this.setData({showName:(null===(t=this.properties)||void 0===t?void 0:t.name)||""})},setShowDateTime(){var t;this.setData({showDateTime:(null===(t=this.properties)||void 0===t?void 0:t.datetime)||""})},setContentClasses(){this.setData({contentClasses:[`${this.data.classPrefix}__content`]})},setChatItemClass(){const{classPrefix:t,showDateTime:e}=this.data,{variant:s,role:a,placement:i}=this.properties,o=[`${t}`,`${t}--${s}`,a,i];e&&o.push(`${t}__header`),this.setData({chatItemClass:o})}},this.lifetimes={created(){this.data.handleLongPress=this.handleLongPress.bind(this)},attached(){this.setShowAvatar(),this.setShowName(),this.setShowDateTime(),this.setContentClasses(),this.setChatItemClass()},detached(){}}}};ChatMessage=__decorate([wxComponent()],ChatMessage);export default ChatMessage;
|
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import props from"./props";import config from"../common/config";const{prefix:prefix}=config,name=`${prefix}-chat-message`;let ChatMessage=class extends SuperComponent{constructor(){super(...arguments),this.options={multipleSlots:!0},this.properties=props,this.data={classPrefix:name,article:"",showAvatar:null,showName:null,showDateTime:null,contentClasses:[],chatItemClass:[]},this.observers={avatar(){this.setShowAvatar()},name(){this.setShowName()},datetime(){this.setShowDateTime()},classPrefix(){this.setContentClasses()},"classPrefix, variant, placement, showDateTime"(){this.setChatItemClass()}},this.methods={handleLongPress(t){this.triggerEvent("message-longpress",{e:t,id:this.data.chatId,longPressPosition:{x:t.detail.x,y:t.detail.y}})},setShowAvatar(){var t;this.setData({showAvatar:(null===(t=this.properties)||void 0===t?void 0:t.avatar)||""})},setShowName(){var t;this.setData({showName:(null===(t=this.properties)||void 0===t?void 0:t.name)||""})},setShowDateTime(){var t;this.setData({showDateTime:(null===(t=this.properties)||void 0===t?void 0:t.datetime)||""})},setContentClasses(){this.setData({contentClasses:[`${this.data.classPrefix}__content`]})},setChatItemClass(){const{classPrefix:t,showDateTime:e}=this.data,{variant:s,role:a,placement:i}=this.properties,o=[`${t}`,`${t}--${s}`,a,i];e&&o.push(`${t}__header`),this.setData({chatItemClass:o})}},this.lifetimes={created(){this.data.handleLongPress=this.handleLongPress.bind(this)},attached(){this.setShowAvatar(),this.setShowName(),this.setShowDateTime(),this.setContentClasses(),this.setChatItemClass()},detached(){}}}};ChatMessage=__decorate([wxComponent()],ChatMessage);export default ChatMessage;
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
.t-chat-message__header .t-chat-message__avatar{padding-top:calc(44rpx + var(--td-spacer,16rpx));}
|
.t-chat-message__header .t-chat-message__avatar{padding-top:calc(44rpx + var(--td-spacer,16rpx));}
|
||||||
.t-chat-message__header .t-chat-message__avatar:empty{padding-top:0;}
|
.t-chat-message__header .t-chat-message__avatar:empty{padding-top:0;}
|
||||||
.t-chat-message.user .t-chat-message__base{padding-right:var(--td-spacer-2,32rpx);}
|
.t-chat-message.user .t-chat-message__base{padding-right:var(--td-spacer-2,32rpx);}
|
||||||
.t-chat-message.user .t-chat-content{max-width:90%;}
|
|
||||||
.t-chat-message.assistant .t-chat-message__base{padding-left:var(--td-spacer-2,32rpx);}
|
.t-chat-message.assistant .t-chat-message__base{padding-left:var(--td-spacer-2,32rpx);}
|
||||||
.t-chat-message.error .t-chat-message__base{padding-left:var(--td-spacer-2,32rpx);}
|
.t-chat-message.error .t-chat-message__base{padding-left:var(--td-spacer-2,32rpx);}
|
||||||
.t-chat-message.error .t-chat-message__text--error{color:var(--td-error-color-6,#d54941);}
|
.t-chat-message.error .t-chat-message__text--error{color:var(--td-error-color-6,#d54941);}
|
||||||
|
|||||||
@@ -1,21 +1,6 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
export default class Dialog extends SuperComponent {
|
export default class Dialog extends SuperComponent {
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>[];
|
|
||||||
options: {
|
options: {
|
||||||
multipleSlots: boolean;
|
multipleSlots: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +1,6 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { ComponentsOptionsType, SuperComponent } from '../common/src/index';
|
import { ComponentsOptionsType, SuperComponent } from '../common/src/index';
|
||||||
export default class Drawer extends SuperComponent {
|
export default class Drawer extends SuperComponent {
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>[];
|
|
||||||
externalClasses: any[];
|
externalClasses: any[];
|
||||||
options: ComponentsOptionsType;
|
options: ComponentsOptionsType;
|
||||||
properties: import("./type").TdDrawerProps;
|
properties: import("./type").TdDrawerProps;
|
||||||
|
|||||||
@@ -1,21 +1,6 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
export default class Fab extends SuperComponent {
|
export default class Fab extends SuperComponent {
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>[];
|
|
||||||
properties: import("./type").TdFabProps;
|
properties: import("./type").TdFabProps;
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
import{__awaiter,__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";import{styles,addUnit,getRect}from"../common/utils";const{prefix:prefix}=config,name=`${prefix}-icon`;let Icon=class extends SuperComponent{constructor(){super(...arguments),this.externalClasses=[`${prefix}-class`],this.properties=props,this.data={componentPrefix:prefix,classPrefix:name,isImage:!1,iconStyle:void 0},this.observers={"name, color, size, style"(){this.setIconStyle()}},this.methods={onTap(t){this.triggerEvent("click",t.detail)},setIconStyle(){const{name:t,color:e,size:o,classPrefix:i}=this.data,s=-1!==t.indexOf("/"),n=addUnit(o),r=e?{color:e}:{},c=o?{"font-size":n}:{},a=Object.assign(Object.assign({},r),c);this.setData({isImage:s},()=>__awaiter(this,void 0,void 0,function*(){if(s){let t=n;t||(yield getRect(this,`.${i}`).then(e=>{t=addUnit(null==e?void 0:e.height)}).catch(()=>{})),a.width=t,a.height=t}this.setData({iconStyle:`${styles(a)}`})}))}}}};Icon=__decorate([wxComponent()],Icon);export default Icon;
|
import{__awaiter,__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";import{styles,addUnit,getRect}from"../common/utils";const{prefix:prefix}=config,name=`${prefix}-icon`;let Icon=class extends SuperComponent{constructor(){super(...arguments),this.externalClasses=[`${prefix}-class`],this.properties=props,this.data={componentPrefix:prefix,classPrefix:name,isImage:!1,iconStyle:void 0},this.observers={"name, color, size, style"(){this.setIconStyle()}},this.methods={onTap(t){this.triggerEvent("click",t.detail)},setIconStyle(){const{name:t,color:e,size:o,classPrefix:i}=this.data,s=-1!==t.indexOf("/"),n=null!==o&&""!==o?addUnit(o):void 0,r=e?{color:e}:{},c=o?{"font-size":n}:{},a=Object.assign(Object.assign({},r),c);this.setData({isImage:s},()=>__awaiter(this,void 0,void 0,function*(){if(s){let t=n;t||(yield getRect(this,`.${i}`).then(e=>{t=addUnit(null==e?void 0:e.height)}).catch(()=>{})),a.width=t,a.height=t}this.setData({iconStyle:`${styles(a)}`})}))}}}};Icon=__decorate([wxComponent()],Icon);export default Icon;
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { RelationsOptions, SuperComponent } from '../common/src/index';
|
import { RelationsOptions, SuperComponent } from '../common/src/index';
|
||||||
export default class Indexes extends SuperComponent {
|
export default class Indexes extends SuperComponent {
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
@@ -18,7 +16,7 @@ export default class Indexes extends SuperComponent {
|
|||||||
showTips: boolean;
|
showTips: boolean;
|
||||||
};
|
};
|
||||||
relations: RelationsOptions;
|
relations: RelationsOptions;
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<WechatMiniprogram.Component.DataOption, WechatMiniprogram.Component.PropertyOption, WechatMiniprogram.Component.MethodOption, WechatMiniprogram.Component.BehaviorOption>[];
|
behaviors: string[];
|
||||||
timer: any;
|
timer: any;
|
||||||
groupTop: any[];
|
groupTop: any[];
|
||||||
sidebar: any;
|
sidebar: any;
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
declare const _default: (funcName?: string) => WechatMiniprogram.Behavior.BehaviorIdentifier<WechatMiniprogram.Component.DataOption, WechatMiniprogram.Component.PropertyOption, WechatMiniprogram.Component.MethodOption, WechatMiniprogram.Component.BehaviorOption>;
|
declare const _default: (funcName?: string) => string;
|
||||||
export default _default;
|
export default _default;
|
||||||
|
|||||||
@@ -1,8 +1,2 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
declare const themeChangeBehavior: string;
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
declare const themeChangeBehavior: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
|
||||||
theme: string;
|
|
||||||
}, WechatMiniprogram.Component.PropertyOption, {
|
|
||||||
_initTheme(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>;
|
|
||||||
export default themeChangeBehavior;
|
export default themeChangeBehavior;
|
||||||
|
|||||||
@@ -1,8 +1,2 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
declare const _default: string;
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
declare const _default: WechatMiniprogram.Behavior.BehaviorIdentifier<WechatMiniprogram.Component.DataOption, WechatMiniprogram.Component.PropertyOption, {
|
|
||||||
resetTouchStatus(): void;
|
|
||||||
touchStart(event: any): void;
|
|
||||||
touchMove(event: any): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>;
|
|
||||||
export default _default;
|
export default _default;
|
||||||
|
|||||||
@@ -1,31 +1 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
export default function transition(): string;
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
export default function transition(): WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
|
||||||
transitionClass: string;
|
|
||||||
transitionDurations: number;
|
|
||||||
className: string;
|
|
||||||
realVisible: boolean;
|
|
||||||
}, {
|
|
||||||
visible: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: any;
|
|
||||||
observer: string;
|
|
||||||
};
|
|
||||||
appear: BooleanConstructor;
|
|
||||||
name: {
|
|
||||||
type: StringConstructor;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
durations: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
optionalTypes: ArrayConstructor[];
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
watchVisible(curr: any, prev: any): void;
|
|
||||||
getDurations(): number[];
|
|
||||||
enter(): void;
|
|
||||||
entered(): void;
|
|
||||||
leave(): void;
|
|
||||||
leaved(): void;
|
|
||||||
onTransitionEnd(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>;
|
|
||||||
|
|||||||
@@ -1,17 +1,2 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
declare const useCustomNavbarBehavior: string;
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
declare const useCustomNavbarBehavior: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>;
|
|
||||||
export default useCustomNavbarBehavior;
|
export default useCustomNavbarBehavior;
|
||||||
|
|||||||
@@ -1,53 +1,10 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
import { TdOverlayProps } from './type';
|
import { TdOverlayProps } from './type';
|
||||||
export interface OverlayProps extends TdOverlayProps {
|
export interface OverlayProps extends TdOverlayProps {
|
||||||
}
|
}
|
||||||
export default class Overlay extends SuperComponent {
|
export default class Overlay extends SuperComponent {
|
||||||
properties: TdOverlayProps;
|
properties: TdOverlayProps;
|
||||||
behaviors: (WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
transitionClass: string;
|
|
||||||
transitionDurations: number;
|
|
||||||
className: string;
|
|
||||||
realVisible: boolean;
|
|
||||||
}, {
|
|
||||||
visible: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: any;
|
|
||||||
observer: string;
|
|
||||||
};
|
|
||||||
appear: BooleanConstructor;
|
|
||||||
name: {
|
|
||||||
type: StringConstructor;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
durations: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
optionalTypes: ArrayConstructor[];
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
watchVisible(curr: any, prev: any): void;
|
|
||||||
getDurations(): number[];
|
|
||||||
enter(): void;
|
|
||||||
entered(): void;
|
|
||||||
leave(): void;
|
|
||||||
leaved(): void;
|
|
||||||
onTransitionEnd(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption> | WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>)[];
|
|
||||||
data: {
|
data: {
|
||||||
prefix: string;
|
prefix: string;
|
||||||
classPrefix: string;
|
classPrefix: string;
|
||||||
|
|||||||
@@ -1,21 +1,6 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent, RelationsOptions } from '../common/src/index';
|
import { SuperComponent, RelationsOptions } from '../common/src/index';
|
||||||
export default class Picker extends SuperComponent {
|
export default class Picker extends SuperComponent {
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>[];
|
|
||||||
properties: import("./type").TdPickerProps;
|
properties: import("./type").TdPickerProps;
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
options: {
|
options: {
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { TdPopoverProps } from './type';
|
import { TdPopoverProps } from './type';
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
export interface PopoverProps extends TdPopoverProps {
|
export interface PopoverProps extends TdPopoverProps {
|
||||||
}
|
}
|
||||||
export default class Popover extends SuperComponent {
|
export default class Popover extends SuperComponent {
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<WechatMiniprogram.Component.DataOption, WechatMiniprogram.Component.PropertyOption, WechatMiniprogram.Component.MethodOption, WechatMiniprogram.Component.BehaviorOption>[];
|
behaviors: string[];
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
options: {
|
options: {
|
||||||
multipleSlots: boolean;
|
multipleSlots: boolean;
|
||||||
|
|||||||
@@ -1,52 +1,9 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { TdPopupProps } from './type';
|
import { TdPopupProps } from './type';
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
export declare type PopupProps = TdPopupProps;
|
export declare type PopupProps = TdPopupProps;
|
||||||
export default class Popup extends SuperComponent {
|
export default class Popup extends SuperComponent {
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
behaviors: (WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
transitionClass: string;
|
|
||||||
transitionDurations: number;
|
|
||||||
className: string;
|
|
||||||
realVisible: boolean;
|
|
||||||
}, {
|
|
||||||
visible: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: any;
|
|
||||||
observer: string;
|
|
||||||
};
|
|
||||||
appear: BooleanConstructor;
|
|
||||||
name: {
|
|
||||||
type: StringConstructor;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
durations: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
optionalTypes: ArrayConstructor[];
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
watchVisible(curr: any, prev: any): void;
|
|
||||||
getDurations(): number[];
|
|
||||||
enter(): void;
|
|
||||||
entered(): void;
|
|
||||||
leave(): void;
|
|
||||||
leaved(): void;
|
|
||||||
onTransitionEnd(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption> | WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>)[];
|
|
||||||
options: {
|
options: {
|
||||||
multipleSlots: boolean;
|
multipleSlots: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<wxs src="./popup.wxs" module="popup"/><wxs src="../common/utils.wxs" module="_"/><view wx:if="{{realVisible}}" style="{{_._style([popup.getPopupStyles(zIndex, distanceTop, placement), style, customStyle])}}" class="{{_.cls(classPrefix, [placement])}} {{transitionClass}} class {{prefix}}-class" bind:transitionend="onTransitionEnd"><view data-prevention="{{preventScrollThrough || (overlayProps ? !!overlayProps.preventScrollThrough : false)}}" bind:touchmove="{{popup.onContentTouchMove}}" class="{{classPrefix}}__content {{prefix}}-class-content"><slot name="content"/><slot/><view class="{{classPrefix}}__close" bind:tap="handleClose"><t-icon name="close" wx:if="{{closeBtn}}" size="64rpx"/><slot name="close-btn" class="{{classPrefix}}-slot"/></view></view></view><t-overlay id="popup-overlay" wx:if="{{showOverlay}}" visible="{{visible}}" usingCustomNavbar="{{usingCustomNavbar}}" z-index="{{overlayProps && overlayProps.zIndex || 11000}}" duration="{{overlayProps && overlayProps.duration || 300}}" background-color="{{overlayProps && overlayProps.backgroundColor || ''}}" prevent-scroll-through="{{preventScrollThrough || (overlayProps ? !!overlayProps.preventScrollThrough : false)}}" bind:tap="handleOverlayClick" custom-style="{{overlayProps && overlayProps.style || ''}}"/>
|
<wxs src="./popup.wxs" module="popup"/><wxs src="../common/utils.wxs" module="_"/><view wx:if="{{realVisible}}" style="{{_._style([popup.getPopupStyles(zIndex, distanceTop, placement, duration), style, customStyle])}}" class="{{_.cls(classPrefix, [placement])}} {{transitionClass}} class {{prefix}}-class" bind:transitionend="onTransitionEnd"><view data-prevention="{{preventScrollThrough || (overlayProps ? !!overlayProps.preventScrollThrough : false)}}" bind:touchmove="{{popup.onContentTouchMove}}" class="{{classPrefix}}__content {{prefix}}-class-content"><slot name="content"/><slot/><view class="{{classPrefix}}__close" bind:tap="handleClose"><t-icon name="close" wx:if="{{closeBtn}}" size="64rpx"/><slot name="close-btn" class="{{classPrefix}}-slot"/></view></view></view><t-overlay id="popup-overlay" wx:if="{{showOverlay}}" visible="{{visible}}" usingCustomNavbar="{{usingCustomNavbar}}" z-index="{{overlayProps && overlayProps.zIndex || 11000}}" duration="{{overlayProps && overlayProps.duration || duration || 300}}" background-color="{{overlayProps && overlayProps.backgroundColor || ''}}" prevent-scroll-through="{{preventScrollThrough || (overlayProps ? !!overlayProps.preventScrollThrough : false)}}" bind:tap="handleOverlayClick" custom-style="{{overlayProps && overlayProps.style || ''}}"/>
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
function getPopupStyles(zIndex, distanceTop, placement) {
|
function getPopupStyles(zIndex, distanceTop, placement, duration) {
|
||||||
var zIndexStyle = zIndex ? 'z-index:' + zIndex + ';' : '';
|
var zIndexStyle = zIndex ? 'z-index:' + zIndex + ';' : '';
|
||||||
if ((placement === 'top' || placement === 'left' || placement === 'right') && distanceTop) {
|
if ((placement === 'top' || placement === 'left' || placement === 'right') && distanceTop) {
|
||||||
zIndexStyle = zIndexStyle + 'top:' + distanceTop + 'px;' + '--td-popup-distance-top:' + distanceTop + 'px;';
|
zIndexStyle = zIndexStyle + 'top:' + distanceTop + 'px;' + '--td-popup-distance-top:' + distanceTop + 'px;';
|
||||||
}
|
}
|
||||||
|
if (duration) {
|
||||||
|
zIndexStyle = zIndexStyle + '--td-popup-transition:all ' + duration + 'ms ease;';
|
||||||
|
}
|
||||||
return zIndexStyle;
|
return zIndexStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,5 +23,5 @@ export default class Search extends SuperComponent {
|
|||||||
handleClear(): void;
|
handleClear(): void;
|
||||||
onConfirm(e: any): void;
|
onConfirm(e: any): void;
|
||||||
onActionClick(): void;
|
onActionClick(): void;
|
||||||
onSelectResultItem(e: any): void;
|
onSelectOption(e: any): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";import{getCharacterLength}from"../common/utils";const{prefix:prefix}=config,name=`${prefix}-search`;let Search=class extends SuperComponent{constructor(){super(...arguments),this.externalClasses=[`${prefix}-class`,`${prefix}-class-input-container`,`${prefix}-class-input`,`${prefix}-class-action`,`${prefix}-class-left`,`${prefix}-class-clear`],this.options={multipleSlots:!0},this.properties=props,this.observers={resultList(e){const{isSelected:t}=this.data;e.length?t?this.setData({isShowResultList:!1,isSelected:!1}):this.setData({isShowResultList:!0}):this.setData({isShowResultList:!1})},"clearTrigger, clearable, disabled, readonly"(){this.updateClearIconVisible()}},this.data={classPrefix:name,prefix:prefix,isShowResultList:!1,isSelected:!1,showClearIcon:!0}}updateClearIconVisible(e=!1){const{clearTrigger:t,disabled:s,readonly:i}=this.properties;s||i?this.setData({showClearIcon:!1}):this.setData({showClearIcon:e||"always"===String(t)})}onInput(e){let{value:t}=e.detail;const{maxcharacter:s}=this.properties;if(s&&"number"==typeof s&&s>0){const{characters:e}=getCharacterLength("maxcharacter",t,s);t=e}this.setData({value:t}),this.triggerEvent("change",{value:t})}onFocus(e){const{value:t}=e.detail;this.updateClearIconVisible(!0),this.triggerEvent("focus",{value:t})}onBlur(e){const{value:t}=e.detail;this.updateClearIconVisible(),this.triggerEvent("blur",{value:t})}handleClear(){this.setData({value:""}),this.triggerEvent("clear",{value:""}),this.triggerEvent("change",{value:""})}onConfirm(e){const{value:t}=e.detail;this.triggerEvent("submit",{value:t})}onActionClick(){this.triggerEvent("action-click")}onSelectResultItem(e){const{index:t}=e.currentTarget.dataset,s=this.properties.resultList[t];this.setData({value:s,isSelected:!0}),this.triggerEvent("change",{value:s}),this.triggerEvent("selectresult",{index:t,item:s})}};Search=__decorate([wxComponent()],Search);export default Search;
|
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";import{getCharacterLength}from"../common/utils";const{prefix:prefix}=config,name=`${prefix}-search`;let Search=class extends SuperComponent{constructor(){super(...arguments),this.externalClasses=[`${prefix}-class`,`${prefix}-class-input-container`,`${prefix}-class-input`,`${prefix}-class-action`,`${prefix}-class-left`,`${prefix}-class-clear`],this.options={multipleSlots:!0},this.properties=props,this.observers={resultList(e){const{isSelected:t}=this.data;e.length?t?this.setData({isShowResultList:!1,isSelected:!1}):this.setData({isShowResultList:!0}):this.setData({isShowResultList:!1})},"clearTrigger, clearable, disabled, readonly"(){this.updateClearIconVisible()}},this.data={classPrefix:name,prefix:prefix,isShowResultList:!1,isSelected:!1,showClearIcon:!0}}updateClearIconVisible(e=!1){const{clearTrigger:t,disabled:s,readonly:i}=this.properties;s||i?this.setData({showClearIcon:!1}):this.setData({showClearIcon:e||"always"===String(t)})}onInput(e){let{value:t}=e.detail;const{maxcharacter:s}=this.properties;if(s&&"number"==typeof s&&s>0){const{characters:e}=getCharacterLength("maxcharacter",t,s);t=e}this.setData({value:t}),this.triggerEvent("change",{value:t,trigger:"input-change"})}onFocus(e){const{value:t}=e.detail;this.updateClearIconVisible(!0),this.triggerEvent("focus",{value:t})}onBlur(e){const{value:t}=e.detail;this.updateClearIconVisible(),this.triggerEvent("blur",{value:t})}handleClear(){this.setData({value:""}),this.triggerEvent("clear",{value:""}),this.triggerEvent("change",{value:"",trigger:"clear"})}onConfirm(e){const{value:t}=e.detail;this.triggerEvent("submit",{value:t})}onActionClick(){this.triggerEvent("action-click")}onSelectOption(e){const{index:t}=e.currentTarget.dataset,s=this.properties.resultList[t];this.setData({value:s,isSelected:!0}),this.triggerEvent("change",{value:s,trigger:"option-click"})}};Search=__decorate([wxComponent()],Search);export default Search;
|
||||||
@@ -1 +1 @@
|
|||||||
<wxs src="../common/utils.wxs" module="_"/><wxs src="./search.wxs" module="_this"></wxs><view style="{{_._style([style, customStyle])}}" class="class {{classPrefix}} {{prefix}}-class"><view class="{{classPrefix}}__input-box {{prefix}}-{{focus ? 'is-focused' : 'not-focused'}} {{classPrefix}}__input-box--{{center ? 'center' : ''}} {{classPrefix}}__input-box--{{shape}} {{prefix}}-class-input-container"><t-icon wx:if="{{leftIcon}}" name="{{leftIcon}}" class="{{prefix}}-icon {{prefix}}-class-left" aria-hidden="{{true}}"/><slot wx:else name="left-icon"/><input type="{{type}}" name="input" maxlength="{{maxlength}}" disabled="{{disabled || readonly}}" class="{{prefix}}-input__keyword {{prefix}}-class-input {{ disabled ? prefix + '-input--disabled' : ''}}" focus="{{focus}}" value="{{value}}" confirm-type="{{confirmType}}" confirm-hold="{{confirmHold}}" cursor="{{cursor}}" adjust-position="{{adjustPosition}}" always-embed="{{alwaysEmbed}}" selection-start="{{selectionStart}}" selection-end="{{selectionEnd}}" hold-keyboard="{{holdKeyboard}}" cursor-spacing="{{cursorSpacing}}" cursor-color="{{cursorColor}}" placeholder="{{placeholder}}" placeholder-style="{{placeholderStyle}}" placeholder-class="{{placeholderClass}} {{classPrefix}}__placeholder {{classPrefix}}__placeholder--{{center ? 'center': 'normal'}}" bind:input="onInput" bind:focus="onFocus" bind:blur="onBlur" bind:confirm="onConfirm"/><view wx:if="{{value !=='' && clearable && showClearIcon}}" class="{{classPrefix}}__clear hotspot-expanded {{prefix}}-class-clear" catch:touchstart="handleClear" aria-role="button" aria-label="清除"><t-icon name="close-circle-filled" size="inherit" color="inherit"/></view></view><view wx:if="{{action}}" class="{{classPrefix}}__search-action {{prefix}}-class-action" catch:tap="onActionClick" aria-role="button">{{action}}</view><slot wx:else name="action"/></view><view wx:if="{{isShowResultList && !isSelected}}" class="{{classPrefix}}__result-list" aria-role="listbox"><t-cell wx:for="{{resultList}}" wx:key="index" data-index="{{index}}" class="{{classPrefix}}__result-item" hover bind:tap="onSelectResultItem" aria-role="option"><rich-text slot="title" nodes="{{_this.highLight(item, value)}}"></rich-text></t-cell></view>
|
<wxs src="../common/utils.wxs" module="_"/><wxs src="./search.wxs" module="_this"></wxs><view style="{{_._style([style, customStyle])}}" class="class {{classPrefix}} {{prefix}}-class"><view class="{{classPrefix}}__input-box {{prefix}}-{{focus ? 'is-focused' : 'not-focused'}} {{classPrefix}}__input-box--{{center ? 'center' : ''}} {{classPrefix}}__input-box--{{shape}} {{prefix}}-class-input-container"><t-icon wx:if="{{leftIcon}}" name="{{leftIcon}}" class="{{prefix}}-icon {{prefix}}-class-left" aria-hidden="{{true}}"/><slot wx:else name="left-icon"/><input type="{{type}}" name="input" maxlength="{{maxlength}}" disabled="{{disabled || readonly}}" class="{{prefix}}-input__keyword {{prefix}}-class-input {{ disabled ? prefix + '-input--disabled' : ''}}" focus="{{focus}}" value="{{value}}" confirm-type="{{confirmType}}" confirm-hold="{{confirmHold}}" cursor="{{cursor}}" adjust-position="{{adjustPosition}}" always-embed="{{alwaysEmbed}}" selection-start="{{selectionStart}}" selection-end="{{selectionEnd}}" hold-keyboard="{{holdKeyboard}}" cursor-spacing="{{cursorSpacing}}" cursor-color="{{cursorColor}}" placeholder="{{placeholder}}" placeholder-style="{{placeholderStyle}}" placeholder-class="{{placeholderClass}} {{classPrefix}}__placeholder {{classPrefix}}__placeholder--{{center ? 'center': 'normal'}}" bind:input="onInput" bind:focus="onFocus" bind:blur="onBlur" bind:confirm="onConfirm"/><view wx:if="{{value !=='' && clearable && showClearIcon}}" class="{{classPrefix}}__clear hotspot-expanded {{prefix}}-class-clear" catch:touchstart="handleClear" aria-role="button" aria-label="清除"><t-icon name="close-circle-filled" size="inherit" color="inherit"/></view></view><view wx:if="{{action}}" class="{{classPrefix}}__search-action {{prefix}}-class-action" catch:tap="onActionClick" aria-role="button">{{action}}</view><slot wx:else name="action"/></view><view wx:if="{{isShowResultList && !isSelected}}" class="{{classPrefix}}__result-list" aria-role="listbox"><t-cell wx:for="{{resultList}}" wx:key="index" data-index="{{index}}" class="{{classPrefix}}__result-item" hover bind:tap="onSelectOption" aria-role="option"><rich-text slot="title" nodes="{{_this.highLight(item, value)}}"></rich-text></t-cell></view>
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
import type { TdStickyProps } from './type';
|
import type { TdStickyProps } from './type';
|
||||||
export interface StickyProps extends TdStickyProps {
|
export interface StickyProps extends TdStickyProps {
|
||||||
@@ -7,7 +5,7 @@ export interface StickyProps extends TdStickyProps {
|
|||||||
export default class Sticky extends SuperComponent {
|
export default class Sticky extends SuperComponent {
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
properties: TdStickyProps;
|
properties: TdStickyProps;
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<WechatMiniprogram.Component.DataOption, WechatMiniprogram.Component.PropertyOption, WechatMiniprogram.Component.MethodOption, WechatMiniprogram.Component.BehaviorOption>[];
|
behaviors: string[];
|
||||||
observers: {
|
observers: {
|
||||||
'offsetTop, disabled, container'(): void;
|
'offsetTop, disabled, container'(): void;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { RelationsOptions, SuperComponent } from '../common/src/index';
|
import { RelationsOptions, SuperComponent } from '../common/src/index';
|
||||||
import { TdTabsProps } from './type';
|
import { TdTabsProps } from './type';
|
||||||
export interface TabsProps extends TdTabsProps {
|
export interface TabsProps extends TdTabsProps {
|
||||||
@@ -8,11 +6,7 @@ export default class Tabs extends SuperComponent {
|
|||||||
options: {
|
options: {
|
||||||
pureDataPattern: RegExp;
|
pureDataPattern: RegExp;
|
||||||
};
|
};
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<WechatMiniprogram.Component.DataOption, WechatMiniprogram.Component.PropertyOption, {
|
behaviors: string[];
|
||||||
resetTouchStatus(): void;
|
|
||||||
touchStart(event: any): void;
|
|
||||||
touchMove(event: any): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>[];
|
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
relations: RelationsOptions;
|
relations: RelationsOptions;
|
||||||
properties: TdTabsProps;
|
properties: TdTabsProps;
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
import { ToastOptionsType } from './index';
|
import { ToastOptionsType } from './index';
|
||||||
declare type Timer = NodeJS.Timeout | null;
|
declare type Timer = NodeJS.Timeout | null;
|
||||||
@@ -9,48 +7,7 @@ export default class Toast extends SuperComponent {
|
|||||||
options: {
|
options: {
|
||||||
multipleSlots: boolean;
|
multipleSlots: boolean;
|
||||||
};
|
};
|
||||||
behaviors: (WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
transitionClass: string;
|
|
||||||
transitionDurations: number;
|
|
||||||
className: string;
|
|
||||||
realVisible: boolean;
|
|
||||||
}, {
|
|
||||||
visible: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: any;
|
|
||||||
observer: string;
|
|
||||||
};
|
|
||||||
appear: BooleanConstructor;
|
|
||||||
name: {
|
|
||||||
type: StringConstructor;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
durations: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
optionalTypes: ArrayConstructor[];
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
watchVisible(curr: any, prev: any): void;
|
|
||||||
getDurations(): number[];
|
|
||||||
enter(): void;
|
|
||||||
entered(): void;
|
|
||||||
leave(): void;
|
|
||||||
leaved(): void;
|
|
||||||
onTransitionEnd(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption> | WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
|
||||||
distanceTop: number;
|
|
||||||
}, {
|
|
||||||
usingCustomNavbar: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: false;
|
|
||||||
};
|
|
||||||
customNavbarHeight: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
value: number;
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
calculateCustomNavbarDistanceTop(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>)[];
|
|
||||||
hideTimer: Timer;
|
hideTimer: Timer;
|
||||||
data: {
|
data: {
|
||||||
prefix: string;
|
prefix: string;
|
||||||
|
|||||||
@@ -1,37 +1,7 @@
|
|||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
/// <reference types="miniprogram-api-typings" />
|
|
||||||
import { SuperComponent } from '../common/src/index';
|
import { SuperComponent } from '../common/src/index';
|
||||||
export default class Transition extends SuperComponent {
|
export default class Transition extends SuperComponent {
|
||||||
externalClasses: string[];
|
externalClasses: string[];
|
||||||
behaviors: WechatMiniprogram.Behavior.BehaviorIdentifier<{
|
behaviors: string[];
|
||||||
transitionClass: string;
|
|
||||||
transitionDurations: number;
|
|
||||||
className: string;
|
|
||||||
realVisible: boolean;
|
|
||||||
}, {
|
|
||||||
visible: {
|
|
||||||
type: BooleanConstructor;
|
|
||||||
value: any;
|
|
||||||
observer: string;
|
|
||||||
};
|
|
||||||
appear: BooleanConstructor;
|
|
||||||
name: {
|
|
||||||
type: StringConstructor;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
durations: {
|
|
||||||
type: NumberConstructor;
|
|
||||||
optionalTypes: ArrayConstructor[];
|
|
||||||
};
|
|
||||||
}, {
|
|
||||||
watchVisible(curr: any, prev: any): void;
|
|
||||||
getDurations(): number[];
|
|
||||||
enter(): void;
|
|
||||||
entered(): void;
|
|
||||||
leave(): void;
|
|
||||||
leaved(): void;
|
|
||||||
onTransitionEnd(): void;
|
|
||||||
}, WechatMiniprogram.Component.BehaviorOption>[];
|
|
||||||
data: {
|
data: {
|
||||||
classPrefix: string;
|
classPrefix: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tdesign-miniprogram",
|
"name": "tdesign-miniprogram",
|
||||||
"version": "1.12.2",
|
"version": "1.12.3",
|
||||||
"title": "tdesign-miniprogram",
|
"title": "tdesign-miniprogram",
|
||||||
"description": "TDesign Component for miniprogram",
|
"description": "TDesign Component for miniprogram",
|
||||||
"main": "miniprogram_dist/index.js",
|
"main": "miniprogram_dist/index.js",
|
||||||
@@ -18,7 +18,8 @@
|
|||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Tencent/tdesign-miniprogram"
|
"url": "https://github.com/Tencent/tdesign-miniprogram",
|
||||||
|
"directory": "packages/tdesign-miniprogram"
|
||||||
},
|
},
|
||||||
"homepage": "https://tdesign.tencent.com/miniprogram",
|
"homepage": "https://tdesign.tencent.com/miniprogram",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tdesign-miniprogram": {
|
"node_modules/tdesign-miniprogram": {
|
||||||
"version": "1.12.2",
|
"version": "1.12.3",
|
||||||
"resolved": "https://registry.npmjs.org/tdesign-miniprogram/-/tdesign-miniprogram-1.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/tdesign-miniprogram/-/tdesign-miniprogram-1.12.3.tgz",
|
||||||
"integrity": "sha512-ZpOdwonT26RRCK/FWbg9tR2lAJ54Hb4PAdyTWu8URWkbKOmSQhn0JCwCtWWRofKbyWCPsCn5NqljobaGh5VCMg==",
|
"integrity": "sha512-F4nMv/ph3yyq9bO4RrJuB9x9VWyKIN6lV1HqFaV4AsR0cpDoBYtGYLPOFejvj0MYDSntSHLMVe1nm0fqsXUaUQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ Page({
|
|||||||
isLoading: false,
|
isLoading: false,
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
hasMore: true
|
hasMore: true,
|
||||||
|
userInfo: null
|
||||||
},
|
},
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
@@ -23,6 +24,13 @@ Page({
|
|||||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||||
this.getTabBar().setData({ selected: 2 });
|
this.getTabBar().setData({ selected: 2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update user info for header
|
||||||
|
const app = getApp();
|
||||||
|
const info = app.globalData.userInfo || wx.getStorageSync('userInfo');
|
||||||
|
if (info) {
|
||||||
|
this.setData({ userInfo: info });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Called by create post page
|
// Called by create post page
|
||||||
@@ -67,7 +75,7 @@ Page({
|
|||||||
return {
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
user: publisher.nickName || publisher.name || '花友',
|
user: publisher.nickName || publisher.name || '花友',
|
||||||
avatar: avatarObj.url || '/assets/default_avatar.png',
|
avatar: avatarObj.url,
|
||||||
content: item.content,
|
content: item.content,
|
||||||
images: (item.imgList || []).map(img => img.url),
|
images: (item.imgList || []).map(img => img.url),
|
||||||
time: item.createdAtStr || '刚刚',
|
time: item.createdAtStr || '刚刚',
|
||||||
|
|||||||
@@ -3,10 +3,8 @@
|
|||||||
<!-- Header with User Info -->
|
<!-- Header with User Info -->
|
||||||
<view class="community-header">
|
<view class="community-header">
|
||||||
<view class="user-info">
|
<view class="user-info">
|
||||||
<view class="user-avatar">
|
<image class="header-avatar" src="{{userInfo.avatar && userInfo.avatar.url ? userInfo.avatar.url : userInfo.avatar}}" mode="aspectFill" />
|
||||||
<text>我</text>
|
<text class="user-name">{{userInfo.nickname || userInfo.name || '花友'}}</text>
|
||||||
</view>
|
|
||||||
<text class="user-name">我的花园</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -31,7 +29,7 @@
|
|||||||
<text class="post-text">{{item.content}}</text>
|
<text class="post-text">{{item.content}}</text>
|
||||||
|
|
||||||
<!-- Image Grid -->
|
<!-- Image Grid -->
|
||||||
<view wx:if="{{item.images.length > 0}}" class="post-images-grid grid-{{item.images.length === 1 ? '1' : (item.images.length <= 4 ? '2' : '3')}}">
|
<view wx:if="{{item.images && item.images.length > 0}}" class="post-images-grid grid-{{item.images.length === 1 ? '1' : (item.images.length === 2 || item.images.length === 4 ? '2' : '3')}}">
|
||||||
<view wx:for="{{item.images}}" wx:for-item="img" wx:key="*this" class="post-image-item" catchtap="previewImage" data-url="{{img}}" data-urls="{{item.images}}">
|
<view wx:for="{{item.images}}" wx:for-item="img" wx:key="*this" class="post-image-item" catchtap="previewImage" data-url="{{img}}" data-urls="{{item.images}}">
|
||||||
<image
|
<image
|
||||||
src="{{img}}"
|
src="{{img}}"
|
||||||
|
|||||||
@@ -29,17 +29,12 @@ page {
|
|||||||
gap: 20rpx;
|
gap: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.community-header .user-avatar {
|
.community-header .header-avatar {
|
||||||
width: 80rpx;
|
width: 80rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
background: linear-gradient(135deg, #E8F5E9, #C8E6C9);
|
|
||||||
color: #558B2F;
|
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
display: flex;
|
background: #f5f5f5;
|
||||||
align-items: center;
|
object-fit: cover;
|
||||||
justify-content: center;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 32rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.community-header .user-name {
|
.community-header .user-name {
|
||||||
@@ -135,31 +130,35 @@ page {
|
|||||||
/* Single Image */
|
/* Single Image */
|
||||||
.grid-1 {
|
.grid-1 {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 70%;
|
width: auto;
|
||||||
|
max-width: 70%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-1 .post-image-item {
|
.grid-1 .post-image-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 16rpx;
|
aspect-ratio: 16 / 9;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-1 .post-image-item t-image {
|
.grid-1 .post-image-item image {
|
||||||
border-radius: 16rpx;
|
border-radius: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2-4 Images (2 columns) */
|
/* 2 or 4 Images (2 columns) */
|
||||||
.grid-2 {
|
.grid-2 {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
width: 75%;
|
width: 500rpx; /* Constrain width for 2 columns to look like partial grid */
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-2 .post-image-item {
|
.grid-2 .post-image-item {
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 5+ Images (3 columns) */
|
/* 3, 5+ Images (3 columns) */
|
||||||
.grid-3 {
|
.grid-3 {
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
width: auto; /* Full available width */
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-3 .post-image-item {
|
.grid-3 .post-image-item {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// pages/garden/add/index.js
|
// pages/garden/add/index.js
|
||||||
import { MOCK_PLANTS, CARE_TASK_ICONS } from '../../../utils/mockData';
|
import { CARE_TASK_ICONS } from '../../../utils/mockData';
|
||||||
import request from '../../../utils/request';
|
import request from '../../../utils/request';
|
||||||
import { requestSubscription, checkSubscriptionSettings } from '../../../utils/subscribe';
|
import { requestSubscription, checkSubscriptionSettings } from '../../../utils/subscribe';
|
||||||
|
|
||||||
|
|||||||
@@ -126,5 +126,18 @@ Page({
|
|||||||
if (!this.data.isLastPage && !this.data.isLoading) {
|
if (!this.data.isLastPage && !this.data.isLoading) {
|
||||||
this.loadPlants(false);
|
this.loadPlants(false);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onShareAppMessage() {
|
||||||
|
return {
|
||||||
|
title: '我的植物花园 - Sundynix Plant',
|
||||||
|
path: '/pages/garden/index'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
onShareTimeline() {
|
||||||
|
return {
|
||||||
|
title: '我的植物花园 - Sundynix Plant'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,6 +8,12 @@
|
|||||||
</view>
|
</view>
|
||||||
<text class="subtitle">今天也要好好照顾它们哦</text>
|
<text class="subtitle">今天也要好好照顾它们哦</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="share-btn-wrap">
|
||||||
|
<button class="share-capsule" open-type="share">
|
||||||
|
<t-icon name="share" size="32rpx" color="#558B2F" />
|
||||||
|
<text>推荐给好友</text>
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="banner-container">
|
<view class="banner-container">
|
||||||
|
|||||||
@@ -40,6 +40,39 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-btn-wrap {
|
||||||
|
position: absolute;
|
||||||
|
top: 40rpx;
|
||||||
|
right: 40rpx;
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-capsule {
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
background: #F1F8E9 !important; /* Lighter background */
|
||||||
|
border-radius: 32rpx;
|
||||||
|
padding: 12rpx 24rpx !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
border: 1px solid rgba(85, 139, 47, 0.2) !important;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(85, 139, 47, 0.08); /* subtle shadow */
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #558B2F;
|
||||||
|
line-height: normal !important;
|
||||||
|
width: auto !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-capsule::after {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.banner-container {
|
.banner-container {
|
||||||
margin: 0 40rpx 24rpx;
|
margin: 0 40rpx 24rpx;
|
||||||
height: 220rpx;
|
height: 220rpx;
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
import request from '../../../utils/request';
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
plantId: '',
|
||||||
|
recordType: 'growth',
|
||||||
|
content: '',
|
||||||
|
image: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad(options) {
|
||||||
|
if (options.plantId) {
|
||||||
|
this.setData({ plantId: options.plantId });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setRecordType(e) {
|
||||||
|
const type = e.currentTarget.dataset.type;
|
||||||
|
this.setData({ recordType: type });
|
||||||
|
},
|
||||||
|
|
||||||
|
onContentInput(e) {
|
||||||
|
this.setData({ content: e.detail.value });
|
||||||
|
},
|
||||||
|
|
||||||
|
handleChooseImage() {
|
||||||
|
wx.chooseMedia({
|
||||||
|
count: 1,
|
||||||
|
mediaType: ['image'],
|
||||||
|
sourceType: ['album', 'camera'],
|
||||||
|
success: (res) => {
|
||||||
|
this.setData({
|
||||||
|
image: res.tempFiles[0].tempFilePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleRemoveImage() {
|
||||||
|
this.setData({ image: '' });
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleAddRecord() {
|
||||||
|
if (!this.data.content.trim()) {
|
||||||
|
wx.showToast({ title: '请填写备注', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.data.plantId) {
|
||||||
|
wx.showToast({ title: '缺少植物ID', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wx.showLoading({ title: '保存中...', mask: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
let ossIds = [];
|
||||||
|
|
||||||
|
// 1. Upload Image if exists
|
||||||
|
if (this.data.image) {
|
||||||
|
const uploadRes = await request.upload(this.data.image);
|
||||||
|
// Correctly extract ID from nested 'file' object based on API response
|
||||||
|
if (uploadRes && uploadRes.file && uploadRes.file.id) {
|
||||||
|
ossIds.push(uploadRes.file.id);
|
||||||
|
} else if (uploadRes && uploadRes.id) {
|
||||||
|
// Fallback just in case
|
||||||
|
ossIds.push(uploadRes.id);
|
||||||
|
} else {
|
||||||
|
console.warn('Upload response structure mismatch:', uploadRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Prepare payload
|
||||||
|
const mapTitle = { growth: '生长记录', repot: '换盆记录', pest: '病虫害记录', other: '日常记录' };
|
||||||
|
const title = mapTitle[this.data.recordType] || '日常记录';
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
plantId: this.data.plantId,
|
||||||
|
ossIds: ossIds,
|
||||||
|
name: title,
|
||||||
|
tag: this.data.recordType,
|
||||||
|
desc: this.data.content.substring(0, 100),
|
||||||
|
content: this.data.content
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. Call Add API
|
||||||
|
await request.post('/plant/growth/add', payload);
|
||||||
|
|
||||||
|
wx.hideLoading();
|
||||||
|
wx.showToast({ title: '保存成功', icon: 'success' });
|
||||||
|
|
||||||
|
// 4. Navigate back, detail page will refresh in onShow
|
||||||
|
setTimeout(() => {
|
||||||
|
wx.navigateBack();
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
wx.hideLoading();
|
||||||
|
console.error('Add record failed', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"navigationBarTitleText": "添加成长记录",
|
||||||
|
"navigationBarBackgroundColor": "#FFFFFF",
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
"backgroundColor": "#F4F6F0",
|
||||||
|
"usingComponents": {
|
||||||
|
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||||
|
"t-image": "tdesign-miniprogram/image/image",
|
||||||
|
"t-button": "tdesign-miniprogram/button/button"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<view class="growth-record-page">
|
||||||
|
<view class="form-container">
|
||||||
|
<!-- Record Type -->
|
||||||
|
<view class="form-group">
|
||||||
|
<text class="form-label">记录类型</text>
|
||||||
|
<view class="chip-group">
|
||||||
|
<view class="chip {{recordType === 'growth' ? 'active' : ''}}" bindtap="setRecordType" data-type="growth">
|
||||||
|
<t-icon name="thumb-up" size="32rpx" />
|
||||||
|
<text>生长</text>
|
||||||
|
</view>
|
||||||
|
<view class="chip {{recordType === 'repot' ? 'active' : ''}}" bindtap="setRecordType" data-type="repot">
|
||||||
|
<t-icon name="swap" size="32rpx" />
|
||||||
|
<text>换盆</text>
|
||||||
|
</view>
|
||||||
|
<view class="chip {{recordType === 'pest' ? 'active' : ''}}" bindtap="setRecordType" data-type="pest">
|
||||||
|
<t-icon name="error-circle" size="32rpx" />
|
||||||
|
<text>病虫害</text>
|
||||||
|
</view>
|
||||||
|
<view class="chip {{recordType === 'other' ? 'active' : ''}}" bindtap="setRecordType" data-type="other">
|
||||||
|
<t-icon name="file" size="32rpx" />
|
||||||
|
<text>其他</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<view class="form-group">
|
||||||
|
<text class="form-label">备注</text>
|
||||||
|
<textarea
|
||||||
|
class="form-textarea"
|
||||||
|
placeholder="记录这一刻的变化..."
|
||||||
|
value="{{content}}"
|
||||||
|
bindinput="onContentInput"
|
||||||
|
maxlength="500"
|
||||||
|
auto-height
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Image Upload -->
|
||||||
|
<view class="form-group">
|
||||||
|
<text class="form-label">添加照片</text>
|
||||||
|
<view class="record-image-upload">
|
||||||
|
<view wx:if="{{image}}" class="uploaded-image-box">
|
||||||
|
<t-image src="{{image}}" mode="aspectFill" width="200rpx" height="200rpx" shape="round" />
|
||||||
|
<view class="remove-img-btn" bindtap="handleRemoveImage">
|
||||||
|
<t-icon name="close" size="32rpx" color="#FFF" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view wx:else class="upload-add-btn" bindtap="handleChooseImage">
|
||||||
|
<t-icon name="add" size="64rpx" color="#999" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="footer-action">
|
||||||
|
<view class="submit-btn" bindtap="handleAddRecord">
|
||||||
|
<text>保存记录</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
/* pages/plant-detail/growth-record/index.wxss */
|
||||||
|
page {
|
||||||
|
background: #F4F6F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.growth-record-page {
|
||||||
|
padding: 32rpx;
|
||||||
|
padding-bottom: 160rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container {
|
||||||
|
background: white;
|
||||||
|
border-radius: 32rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 48rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chip Styles */
|
||||||
|
.chip-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip {
|
||||||
|
padding: 20rpx 32rpx;
|
||||||
|
background: #F5F5F5;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
border: 2rpx solid transparent;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip.active {
|
||||||
|
background: #E8F5E9;
|
||||||
|
color: #558B2F;
|
||||||
|
border-color: #558B2F;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip:active {
|
||||||
|
transform: scale(0.96);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Textarea */
|
||||||
|
.form-textarea {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 200rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
border: 2rpx solid #e0e0e0;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: #FAFAFA;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-textarea:focus {
|
||||||
|
background: white;
|
||||||
|
border-color: #558B2F;
|
||||||
|
box-shadow: 0 0 0 6rpx rgba(85, 139, 47, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Image Upload */
|
||||||
|
.record-image-upload {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-add-btn {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
background: #FAFAFA;
|
||||||
|
border: 2rpx dashed #d9d9d9;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-add-btn:active {
|
||||||
|
background: #F0F0F0;
|
||||||
|
border-color: #558B2F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploaded-image-box {
|
||||||
|
position: relative;
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-img-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: -16rpx;
|
||||||
|
right: -16rpx;
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 10;
|
||||||
|
backdrop-filter: blur(4rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer Action */
|
||||||
|
.footer-action {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 32rpx;
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.05);
|
||||||
|
z-index: 100;
|
||||||
|
padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 96rpx;
|
||||||
|
background: linear-gradient(135deg, #689F38, #558B2F);
|
||||||
|
border-radius: 48rpx;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: 0 8rpx 24rpx rgba(85, 139, 47, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
filter: brightness(0.95);
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ Page({
|
|||||||
data: {
|
data: {
|
||||||
currentPlant: null,
|
currentPlant: null,
|
||||||
activeImageIndex: 0,
|
activeImageIndex: 0,
|
||||||
activeTab: 'care',
|
activeTab: 'info',
|
||||||
careLogs: [],
|
careLogs: [],
|
||||||
displayCareLogs: [],
|
displayCareLogs: [],
|
||||||
displayCareLimit: 5,
|
displayCareLimit: 5,
|
||||||
@@ -51,22 +51,46 @@ Page({
|
|||||||
return { ...cp, taskIcon: iconObj };
|
return { ...cp, taskIcon: iconObj };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Calculate days planted and format date
|
||||||
|
let adoptionDate = '未知';
|
||||||
|
let daysPlanted = 0;
|
||||||
|
if (plant.plantTime) {
|
||||||
|
const start = new Date(plant.plantTime);
|
||||||
|
const now = new Date();
|
||||||
|
const diffTime = now - start;
|
||||||
|
if (diffTime > 0) {
|
||||||
|
daysPlanted = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||||||
|
}
|
||||||
|
adoptionDate = plant.plantTime.split('T')[0];
|
||||||
|
}
|
||||||
|
|
||||||
this.setData({
|
this.setData({
|
||||||
currentPlant: {
|
currentPlant: {
|
||||||
...plant,
|
...plant,
|
||||||
|
location: plant.placement || '',
|
||||||
|
adoptionDate: adoptionDate,
|
||||||
|
daysPlanted: daysPlanted,
|
||||||
careSchedule: carePlans
|
careSchedule: carePlans
|
||||||
},
|
},
|
||||||
swiperImages: swiperImages,
|
swiperImages: swiperImages,
|
||||||
// Map logs and records directly from plant detail response
|
// Map logs and records directly from plant detail response
|
||||||
careLogs: this.processLogs(plant.careRecords || []),
|
careLogs: this.processLogs(plant.careRecords || []),
|
||||||
records: (plant.growthRecords || plant.recordList || []).map(item => ({
|
records: (plant.growthRecords || plant.recordList || []).map(item => {
|
||||||
|
// Extract image URL safely
|
||||||
|
let imageUrl = '';
|
||||||
|
if (item.imgList && item.imgList.length > 0) {
|
||||||
|
imageUrl = item.imgList[0].url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
date: item.createdAtStr ? item.createdAtStr.split(' ')[0] : '',
|
date: item.createdAtStr ? item.createdAtStr.split(' ')[0] : '',
|
||||||
type: item.recordType || 'growth',
|
type: item.tag || 'growth',
|
||||||
title: item.title,
|
title: item.name || '成长记录',
|
||||||
content: item.content,
|
content: item.content || item.desc || '',
|
||||||
image: (item.imgList && item.imgList.length > 0) ? item.imgList[0].url : ''
|
image: imageUrl
|
||||||
}))
|
};
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
this.updateDisplayLogs();
|
this.updateDisplayLogs();
|
||||||
@@ -203,78 +227,21 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Growth Record Logic
|
// Growth Record Logic
|
||||||
openGrowthModal() {
|
|
||||||
this.setData({
|
|
||||||
showGrowthModal: true,
|
|
||||||
newRecordContent: '',
|
|
||||||
newRecordType: 'growth',
|
|
||||||
newRecordImage: ''
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onGrowthPopupVisibleChange(e) { this.setData({ showGrowthModal: e.detail.visible }); },
|
|
||||||
closeGrowthModal() { this.setData({ showGrowthModal: false }); },
|
|
||||||
|
|
||||||
setRecordType(e) {
|
|
||||||
const type = e.currentTarget.dataset.type;
|
|
||||||
if (e.detail.checked) {
|
|
||||||
this.setData({ newRecordType: type });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setRecordTypeByTap(e) {
|
|
||||||
const type = e.currentTarget.dataset.type;
|
|
||||||
this.setData({ newRecordType: type });
|
|
||||||
},
|
|
||||||
onRecordContentInput(e) { this.setData({ newRecordContent: e.detail.value }); },
|
|
||||||
|
|
||||||
handleChooseRecordImage() {
|
|
||||||
wx.chooseMedia({
|
|
||||||
count: 1,
|
|
||||||
mediaType: ['image'],
|
|
||||||
sourceType: ['album', 'camera'],
|
|
||||||
success: (res) => {
|
|
||||||
this.setData({
|
|
||||||
newRecordImage: res.tempFiles[0].tempFilePath
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
handleRemoveRecordImage() {
|
|
||||||
this.setData({ newRecordImage: '' });
|
|
||||||
},
|
|
||||||
|
|
||||||
handlePreviewRecordImage(e) {
|
handlePreviewRecordImage(e) {
|
||||||
const src = e.currentTarget.dataset.src;
|
const src = e.currentTarget.dataset.src;
|
||||||
const fullPath = (src.indexOf('http') === 0 || src.indexOf('wxfile') === 0) ? src : `/assets/${src}`;
|
if (!src) return;
|
||||||
|
|
||||||
wx.previewImage({
|
wx.previewImage({
|
||||||
current: fullPath,
|
current: src,
|
||||||
urls: [fullPath]
|
urls: [src]
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleAddRecord() {
|
openGrowthModal() {
|
||||||
if (!this.data.newRecordContent.trim()) return;
|
if (this.data.currentPlant && this.data.currentPlant.id) {
|
||||||
|
wx.navigateTo({
|
||||||
const mapTitle = { growth: '生长记录', repot: '换盆记录', pest: '病虫害记录', other: '日常记录' };
|
url: `/pages/plant-detail/growth-record/index?plantId=${this.data.currentPlant.id}`
|
||||||
const now = new Date();
|
|
||||||
const dateStr = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
|
|
||||||
|
|
||||||
const record = {
|
|
||||||
id: Date.now().toString(),
|
|
||||||
date: dateStr,
|
|
||||||
type: this.data.newRecordType,
|
|
||||||
title: mapTitle[this.data.newRecordType],
|
|
||||||
content: this.data.newRecordContent,
|
|
||||||
image: this.data.newRecordImage
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setData({
|
|
||||||
records: [record, ...this.data.records],
|
|
||||||
showGrowthModal: false
|
|
||||||
});
|
});
|
||||||
this.updateDisplayRecords();
|
|
||||||
|
|
||||||
wx.showToast({ title: '记录成功', icon: 'success' });
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,14 +32,69 @@
|
|||||||
<view class="detail-content">
|
<view class="detail-content">
|
||||||
<!-- Custom Tabs -->
|
<!-- Custom Tabs -->
|
||||||
<view class="pd-tabs">
|
<view class="pd-tabs">
|
||||||
|
<view class="pd-tab-btn {{activeTab === 'info' ? 'active' : ''}}" bindtap="switchTab" data-tab="info">
|
||||||
|
基础档案
|
||||||
|
</view>
|
||||||
<view class="pd-tab-btn {{activeTab === 'care' ? 'active' : ''}}" bindtap="switchTab" data-tab="care">
|
<view class="pd-tab-btn {{activeTab === 'care' ? 'active' : ''}}" bindtap="switchTab" data-tab="care">
|
||||||
养护记录
|
养护记录
|
||||||
</view>
|
</view>
|
||||||
<view class="pd-tab-btn {{activeTab === 'archive' ? 'active' : ''}}" bindtap="switchTab" data-tab="archive">
|
<view class="pd-tab-btn {{activeTab === 'growth' ? 'active' : ''}}" bindtap="switchTab" data-tab="growth">
|
||||||
植物档案
|
成长档案
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- Info Tab Scroll View -->
|
||||||
|
<scroll-view
|
||||||
|
scroll-y="{{!showGrowthModal}}"
|
||||||
|
class="pd-content"
|
||||||
|
enhanced="{{true}}"
|
||||||
|
show-scrollbar="{{false}}"
|
||||||
|
hidden="{{activeTab !== 'info'}}"
|
||||||
|
>
|
||||||
|
<view class="archive-view fadeIn">
|
||||||
|
<view class="archive-identity-card">
|
||||||
|
<view class="aic-header">
|
||||||
|
<view class="aic-badge">🏆 元老级植物</view>
|
||||||
|
<view class="aic-location">
|
||||||
|
<t-icon name="location" size="28rpx" color="#388E3C" />
|
||||||
|
<text>{{currentPlant.location || '位置未定'}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="aic-stats">
|
||||||
|
<view class="aic-stat-item">
|
||||||
|
<text class="label">入家时间</text>
|
||||||
|
<text class="value">{{currentPlant.adoptionDate || '未知'}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="aic-stat-item">
|
||||||
|
<text class="label">入住天数</text>
|
||||||
|
<text class="value">{{currentPlant.daysPlanted}} 天</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- New detail fields -->
|
||||||
|
<view class="aic-extra-info">
|
||||||
|
<view wx:if="{{currentPlant.potMaterial}}" class="aic-info-row">
|
||||||
|
<text class="label">花园材质:</text>
|
||||||
|
<text class="value">{{currentPlant.potMaterial}}</text>
|
||||||
|
</view>
|
||||||
|
<view wx:if="{{currentPlant.potSize}}" class="aic-info-row">
|
||||||
|
<text class="label">花园大小:</text>
|
||||||
|
<text class="value">{{currentPlant.potSize}}</text>
|
||||||
|
</view>
|
||||||
|
<view wx:if="{{currentPlant.sunlight}}" class="aic-info-row">
|
||||||
|
<text class="label">光照条件:</text>
|
||||||
|
<text class="value">{{currentPlant.sunlight}}</text>
|
||||||
|
</view>
|
||||||
|
<view wx:if="{{currentPlant.plantingMaterial}}" class="aic-info-row">
|
||||||
|
<text class="label">植料土壤:</text>
|
||||||
|
<text class="value">{{currentPlant.plantingMaterial}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
<!-- Care Tab Scroll View -->
|
<!-- Care Tab Scroll View -->
|
||||||
<scroll-view
|
<scroll-view
|
||||||
scroll-y="{{!showGrowthModal}}"
|
scroll-y="{{!showGrowthModal}}"
|
||||||
@@ -91,58 +146,15 @@
|
|||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<!-- Archive Tab Scroll View -->
|
<!-- Growth Tab Scroll View -->
|
||||||
<scroll-view
|
<scroll-view
|
||||||
scroll-y="{{!showGrowthModal}}"
|
scroll-y="{{!showGrowthModal}}"
|
||||||
class="pd-content"
|
class="pd-content"
|
||||||
enhanced="{{true}}"
|
enhanced="{{true}}"
|
||||||
show-scrollbar="{{false}}"
|
show-scrollbar="{{false}}"
|
||||||
hidden="{{activeTab !== 'archive'}}"
|
hidden="{{activeTab !== 'growth'}}"
|
||||||
>
|
>
|
||||||
<view class="archive-view fadeIn">
|
<view class="archive-view fadeIn">
|
||||||
<view class="archive-identity-card">
|
|
||||||
<view class="aic-header">
|
|
||||||
<view class="aic-badge">🏆 元老级植物</view>
|
|
||||||
<view class="aic-location">
|
|
||||||
<t-icon name="location" size="28rpx" color="#388E3C" />
|
|
||||||
<text>{{currentPlant.location || '位置未定'}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="aic-stats">
|
|
||||||
<view class="aic-stat-item">
|
|
||||||
<text class="label">入家时间</text>
|
|
||||||
<text class="value">{{currentPlant.adoptionDate || '未知'}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="aic-stat-item">
|
|
||||||
<text class="label">入住天数</text>
|
|
||||||
<text class="value">{{currentPlant.daysPlanted}} 天</text>
|
|
||||||
</view>
|
|
||||||
<view class="aic-stat-item">
|
|
||||||
<text class="label">养护次数</text>
|
|
||||||
<text class="value">{{careLogs.length || 0}} 次</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- New detail fields -->
|
|
||||||
<view class="aic-extra-info">
|
|
||||||
<view wx:if="{{currentPlant.potMaterial}}" class="aic-info-row">
|
|
||||||
<text class="label">花园材质:</text>
|
|
||||||
<text class="value">{{currentPlant.potMaterial}}</text>
|
|
||||||
</view>
|
|
||||||
<view wx:if="{{currentPlant.potSize}}" class="aic-info-row">
|
|
||||||
<text class="label">花园大小:</text>
|
|
||||||
<text class="value">{{currentPlant.potSize}}</text>
|
|
||||||
</view>
|
|
||||||
<view wx:if="{{currentPlant.sunlight}}" class="aic-info-row">
|
|
||||||
<text class="label">光照条件:</text>
|
|
||||||
<text class="value">{{currentPlant.sunlight}}</text>
|
|
||||||
</view>
|
|
||||||
<view wx:if="{{currentPlant.plantingMaterial}}" class="aic-info-row">
|
|
||||||
<text class="label">植料土壤:</text>
|
|
||||||
<text class="value">{{currentPlant.plantingMaterial}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="section-header">
|
<view class="section-header">
|
||||||
<text class="h3">成长记录</text>
|
<text class="h3">成长记录</text>
|
||||||
@@ -166,11 +178,11 @@
|
|||||||
<text>{{item.title}}</text>
|
<text>{{item.title}}</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="timeline-desc">{{item.content}}</text>
|
<text class="timeline-desc">{{item.content}}</text>
|
||||||
<t-image
|
<image
|
||||||
wx:if="{{item.image}}"
|
wx:if="{{item.image}}"
|
||||||
src="{{item.image}}"
|
src="{{item.image}}"
|
||||||
mode="widthFix"
|
mode="aspectFill"
|
||||||
width="100%"
|
style="width: 220rpx; height: 220rpx; border-radius: 16rpx; margin-top: 16rpx;"
|
||||||
class="timeline-img"
|
class="timeline-img"
|
||||||
bindtap="handlePreviewRecordImage"
|
bindtap="handlePreviewRecordImage"
|
||||||
data-src="{{item.image}}"
|
data-src="{{item.image}}"
|
||||||
@@ -196,74 +208,5 @@
|
|||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Growth Record Popup -->
|
|
||||||
<t-popup visible="{{showGrowthModal}}" bind:visible-change="onGrowthPopupVisibleChange" placement="center" prevent-scroll-through>
|
|
||||||
<view class="edit-modal">
|
|
||||||
<view class="modal-header" catchtouchmove="preventTouchMove">
|
|
||||||
<text class="modal-title">添加成长记录</text>
|
|
||||||
<view class="close-btn" bindtap="closeGrowthModal">
|
|
||||||
<t-icon name="close" size="40rpx" color="#666" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="modal-body">
|
|
||||||
<!-- Record Type -->
|
|
||||||
<view class="form-group">
|
|
||||||
<text class="form-label">记录类型</text>
|
|
||||||
<view class="chip-group">
|
|
||||||
<view class="chip {{newRecordType === 'growth' ? 'active' : ''}}" bindtap="setRecordTypeByTap" data-type="growth">
|
|
||||||
<t-icon name="thumb-up" size="28rpx" />
|
|
||||||
<text>生长</text>
|
|
||||||
</view>
|
|
||||||
<view class="chip {{newRecordType === 'repot' ? 'active' : ''}}" bindtap="setRecordTypeByTap" data-type="repot">
|
|
||||||
<t-icon name="swap" size="28rpx" />
|
|
||||||
<text>换盆</text>
|
|
||||||
</view>
|
|
||||||
<view class="chip {{newRecordType === 'pest' ? 'active' : ''}}" bindtap="setRecordTypeByTap" data-type="pest">
|
|
||||||
<t-icon name="error-circle" size="28rpx" />
|
|
||||||
<text>病虫害</text>
|
|
||||||
</view>
|
|
||||||
<view class="chip {{newRecordType === 'other' ? 'active' : ''}}" bindtap="setRecordTypeByTap" data-type="other">
|
|
||||||
<t-icon name="file" size="28rpx" />
|
|
||||||
<text>其他</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- Content -->
|
|
||||||
<view class="form-group">
|
|
||||||
<text class="form-label">备注</text>
|
|
||||||
<textarea
|
|
||||||
class="form-textarea"
|
|
||||||
placeholder="记录这一刻的变化..."
|
|
||||||
value="{{newRecordContent}}"
|
|
||||||
bindinput="onRecordContentInput"
|
|
||||||
auto-height
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- Image Upload -->
|
|
||||||
<view class="form-group">
|
|
||||||
<text class="form-label">添加照片</text>
|
|
||||||
<view class="record-image-upload">
|
|
||||||
<view wx:if="{{newRecordImage}}" class="uploaded-image-box">
|
|
||||||
<t-image src="{{newRecordImage}}" mode="aspectFill" width="160rpx" height="160rpx" shape="round" />
|
|
||||||
<view class="remove-img-btn" bindtap="handleRemoveRecordImage">
|
|
||||||
<t-icon name="close" size="24rpx" color="#FFF" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view wx:else class="upload-add-btn" bindtap="handleChooseRecordImage">
|
|
||||||
<t-icon name="add" size="48rpx" color="#999" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="modal-footer" catchtouchmove="preventTouchMove">
|
|
||||||
<view class="submit-btn" bindtap="handleAddRecord">
|
|
||||||
<text>保存记录</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</t-popup>
|
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
import request from '../../../utils/request';
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
userLevel: 0,
|
||||||
|
userLevelTag: '',
|
||||||
|
currentExp: 0,
|
||||||
|
maxExp: 1000,
|
||||||
|
maxExp: 1000,
|
||||||
|
nextLevelExp: 1000,
|
||||||
|
showLevelsPopup: false,
|
||||||
|
allLevels: [],
|
||||||
|
|
||||||
|
badges: [
|
||||||
|
{ id: 1, name: '初级播种者', desc: '成功种植第一棵植物', iconName: 'flower', color: '#4CAF50', unlocked: true },
|
||||||
|
{ id: 2, name: '勤劳园丁', desc: '总养护次数达到10次', iconName: 'tools', color: '#2196F3', unlocked: true },
|
||||||
|
{ id: 3, name: '植物专家', desc: '成功识别50种植物', iconName: 'scan', color: '#9C27B0', unlocked: false, progress: '12/50' },
|
||||||
|
{ id: 4, name: '全勤奖', desc: '连续30天打卡', iconName: 'calendar', color: '#FF9800', unlocked: false, progress: '5/30' },
|
||||||
|
{ id: 5, name: '分享大师', desc: '发布10条动态', iconName: 'share', color: '#E91E63', unlocked: false, progress: '3/10' },
|
||||||
|
{ id: 6, name: '收藏家', desc: '收藏20个植物百科', iconName: 'star', color: '#FFC107', unlocked: false, progress: '8/20' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
this.fetchData();
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchData() {
|
||||||
|
wx.showLoading({ title: '加载中...' });
|
||||||
|
try {
|
||||||
|
const [levelRes, profileRes] = await Promise.all([
|
||||||
|
request.get('/config/level/list'),
|
||||||
|
request.get('/profile/detail')
|
||||||
|
]);
|
||||||
|
this.processData(levelRes, profileRes);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Fetch badges data failed', e);
|
||||||
|
wx.showToast({ title: '加载失败', icon: 'none' });
|
||||||
|
} finally {
|
||||||
|
wx.hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
processData(levelsData, profile) {
|
||||||
|
const levelList = levelsData && levelsData.list ? levelsData.list : [];
|
||||||
|
levelList.sort((a, b) => a.minSunlight - b.minSunlight); // Ensure sorted by threshold
|
||||||
|
|
||||||
|
const totalSunlight = profile.totalSunlight || 0;
|
||||||
|
|
||||||
|
// Find current level: highest level where minSunlight <= totalSunlight
|
||||||
|
let currentLevelConfig = null;
|
||||||
|
for (let i = levelList.length - 1; i >= 0; i--) {
|
||||||
|
if (totalSunlight >= levelList[i].minSunlight) {
|
||||||
|
currentLevelConfig = levelList[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if no level matched (e.g. 0 sunlight but level 1 starts at 0? Logic handles it if sorted)
|
||||||
|
if (!currentLevelConfig && levelList.length > 0) {
|
||||||
|
// Fallback to absolute lowest or specific logic
|
||||||
|
// Assuming level 1 starts at 0, it should be caught.
|
||||||
|
currentLevelConfig = levelList[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentLevelVal = currentLevelConfig ? currentLevelConfig.level : 0;
|
||||||
|
|
||||||
|
// Find next level
|
||||||
|
const nextLevelConfig = levelList.find(l => l.minSunlight > totalSunlight);
|
||||||
|
|
||||||
|
let maxExp = 0;
|
||||||
|
let nextPerk = '';
|
||||||
|
|
||||||
|
if (nextLevelConfig) {
|
||||||
|
maxExp = nextLevelConfig.minSunlight;
|
||||||
|
nextPerk = nextLevelConfig.perks;
|
||||||
|
} else {
|
||||||
|
// Max level
|
||||||
|
maxExp = totalSunlight > 0 ? totalSunlight : 100;
|
||||||
|
nextPerk = '已达到最高等级';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity
|
||||||
|
if (maxExp < totalSunlight) maxExp = totalSunlight;
|
||||||
|
|
||||||
|
const tag = currentLevelConfig ? `Lv.${currentLevelVal} ${currentLevelConfig.title}` : 'Lv.0 园艺新手';
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
userLevel: currentLevelVal,
|
||||||
|
userLevelTag: tag,
|
||||||
|
currentExp: totalSunlight,
|
||||||
|
maxExp: maxExp,
|
||||||
|
nextLevelExp: Math.max(0, maxExp - totalSunlight),
|
||||||
|
nextPerk: nextPerk,
|
||||||
|
allLevels: levelList // Save for popup
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
showLevelList() {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: `/pages/profile/badges/level-detail/index?sunlight=${this.data.currentExp}`
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"navigationBarTitleText": "成就徽章",
|
||||||
|
"navigationBarBackgroundColor": "#F4F6F0",
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
"usingComponents": {
|
||||||
|
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||||
|
}
|
||||||
|
}
|
||||||