提交 3ffd0037 编写于 作者: DCloud-yyl's avatar DCloud-yyl

Merge branch 'dev' into alpha

...@@ -55,29 +55,29 @@ ...@@ -55,29 +55,29 @@
console.log(action); console.log(action);
switch (action) { switch (action) {
case 'switchTab': case 'switchTab':
uni.switchTab({ uni.webView.switchTab({
url: '/pages/tabBar/API' url: '/pages/tabBar/API'
}); });
break; break;
case 'reLaunch': case 'reLaunch':
uni.reLaunch({ uni.webView.reLaunch({
url: '/pages/tabBar/component' url: '/pages/tabBar/component'
}); });
break; break;
case 'navigateBack': case 'navigateBack':
uni.navigateBack({ uni.webView.navigateBack({
delta: 1 delta: 1
}); });
break; break;
case 'getEnv': case 'getEnv':
uni.getEnv((res) => { uni.webView.getEnv((res) => {
uni.postMessage({ uni.postMessage({
data: res data: res
}) })
}); });
break; break;
default: default:
uni[action]({ uni.webView[action]({
url: '/pages/component/button/button' url: '/pages/component/button/button'
}); });
break; break;
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
}) })
// }); // });
document.querySelector("#postMessage").addEventListener('click', function() { document.querySelector("#postMessage").addEventListener('click', function() {
uni.postMessage({ uni.webView.postMessage({
data: { data: {
action: 'message' action: 'message'
} }
......
...@@ -14,12 +14,6 @@ ...@@ -14,12 +14,6 @@
"navigationBarTitleText": "view" "navigationBarTitleText": "view"
} }
}, },
{
"path": "pages/component/view/view-draw",
"style": {
"navigationBarTitleText": "DrawableContext"
}
},
{ {
"path": "pages/component/scroll-view/scroll-view", "path": "pages/component/scroll-view/scroll-view",
"style": { "style": {
...@@ -199,6 +193,32 @@ ...@@ -199,6 +193,32 @@
"style": { "style": {
"navigationBarTitleText": "general-event" "navigationBarTitleText": "general-event"
} }
},
{
"path": "pages/component/unicloud-db-contacts/list",
"style": {
"navigationBarTitleText": "联系人",
"enablePullDownRefresh": true
}
},
{
"path": "pages/component/unicloud-db-contacts/add",
"style": {
"navigationBarTitleText": "新增联系人"
}
},
{
"path": "pages/component/unicloud-db-contacts/edit",
"style": {
"navigationBarTitleText": "编辑联系人",
"navigationStyle": "custom"
}
},
{
"path": "pages/component/unicloud-db-contacts/detail",
"style": {
"navigationBarTitleText": ""
}
}, },
{ {
"path": "pages/tabBar/API", "path": "pages/tabBar/API",
...@@ -844,7 +864,7 @@ ...@@ -844,7 +864,7 @@
{ {
"path": "pages/template/scroll-sticky/scroll-sticky", "path": "pages/template/scroll-sticky/scroll-sticky",
"style": { "style": {
"navigationBarTitleText": "滚动吸顶" "navigationBarTitleText": "scroll-view自定义滚动吸顶"
} }
}, },
{ {
...@@ -958,7 +978,31 @@ ...@@ -958,7 +978,31 @@
"navigationBarTitleText": "", "navigationBarTitleText": "",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
} },
{
"path": "pages/component/sticky-header/sticky-header",
"style": {
"navigationBarTitleText": "sticky-header",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/API/element-takesnapshot/element-takesnapshot",
"style" :
{
"navigationBarTitleText" : "takeSnapshot",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/API/element-draw/element-draw",
"style" :
{
"navigationBarTitleText" : "getDrawableContext",
"enablePullDownRefresh" : false
}
}
], ],
"globalStyle": { "globalStyle": {
"pageOrientation": "portrait", "pageOrientation": "portrait",
...@@ -1009,4 +1053,4 @@ ...@@ -1009,4 +1053,4 @@
"query": "" //启动参数,在页面的onLoad函数里面得到 "query": "" //启动参数,在页面的onLoad函数里面得到
}] }]
} }
} }
\ No newline at end of file
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
<scroll-view style="flex: 1"> <scroll-view style="flex: 1">
<!-- #endif --> <!-- #endif -->
<view> <view>
<view ref="draw-text-view" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view> <view id="draw-text-view" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view>
<view ref="draw-line-view" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view> <view id="draw-line-view" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view>
<view ref="draw-circle-view" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view> <view id="draw-circle-view" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view>
<view ref="draw-dash-line" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view> <view id="draw-dash-line" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view>
<view ref="draw-house" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view> <view id="draw-house" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view>
<view ref="draw-style" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view> <view id="draw-style" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view>
<view ref="draw-odd" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view> <view id="draw-odd" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view>
<view ref="draw-arcto" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view> <view id="draw-arcto" style="width: 750rpx;height: 550rpx; background-color: lightgray;margin: 30rpx 0rpx;"></view>
</view> </view>
<!-- #ifdef APP --> <!-- #ifdef APP -->
</scroll-view> </scroll-view>
...@@ -57,68 +57,68 @@ ...@@ -57,68 +57,68 @@
}, },
methods: { methods: {
drawText() { drawText() {
let element = (this.$refs['draw-text-view'] as Element) let element = uni.getElementById('draw-text-view')
let ctx = element.getDrawableContext() let ctx = element!.getDrawableContext()
let width = element.getBoundingClientRect().width let width = element.getBoundingClientRect().width
ctx!!.reset() ctx!.reset()
ctx!!.font = "15px" ctx.font = "15px"
ctx!.textAlign = "center" ctx.textAlign = "center"
for (var i = 0; i < this.texts.length; i++) { for (var i = 0; i < this.texts.length; i++) {
let value = this.texts[i] let value = this.texts[i]
if (i % 2 == 0) { if (i % 2 == 0) {
ctx!!.fillText(value, width / 2, (20 * (i + 1))) ctx.fillText(value, width / 2, (20 * (i + 1)))
} else { } else {
ctx!!.strokeText(value, width / 2, (20 * (i + 1))) ctx.strokeText(value, width / 2, (20 * (i + 1)))
} }
} }
ctx!!.update() ctx.update()
}, },
drawLines() { drawLines() {
let ctx = (this.$refs['draw-line-view'] as Element).getDrawableContext() let ctx = uni.getElementById('draw-line-view')!.getDrawableContext()
ctx!!.reset() ctx!.reset()
ctx!!.lineWidth = 10; ctx.lineWidth = 10;
["round", "bevel", "miter"].forEach((join, i) => { ["round", "bevel", "miter"].forEach((join, i) => {
ctx!.lineJoin = join; ctx.lineJoin = join;
ctx!.beginPath(); ctx.beginPath();
ctx!.moveTo(5, 10 + i * 40); ctx.moveTo(5, 10 + i * 40);
ctx!.lineTo(50, 50 + i * 40); ctx.lineTo(50, 50 + i * 40);
ctx!.lineTo(90, 10 + i * 40); ctx.lineTo(90, 10 + i * 40);
ctx!.lineTo(130, 50 + i * 40); ctx.lineTo(130, 50 + i * 40);
ctx!.lineTo(170, 10 + i * 40); ctx.lineTo(170, 10 + i * 40);
ctx!.stroke(); ctx.stroke();
}); });
ctx!!.lineWidth = 1 ctx.lineWidth = 1
var space = 170 var space = 170
ctx!.strokeStyle = '#09f'; ctx.strokeStyle = '#09f';
ctx!.beginPath(); ctx.beginPath();
ctx!.moveTo(10 + space, 10); ctx.moveTo(10 + space, 10);
ctx!.lineTo(140 + space, 10); ctx.lineTo(140 + space, 10);
ctx!.moveTo(10 + space, 140); ctx.moveTo(10 + space, 140);
ctx!.lineTo(140 + space, 140); ctx.lineTo(140 + space, 140);
ctx!.stroke(); ctx.stroke();
// Draw lines // Draw lines
ctx!.strokeStyle = 'black'; ctx.strokeStyle = 'black';
['butt', 'round', 'square'].forEach((lineCap, i) => { ['butt', 'round', 'square'].forEach((lineCap, i) => {
ctx!.lineWidth = 15; ctx.lineWidth = 15;
ctx!.lineCap = lineCap; ctx.lineCap = lineCap;
ctx!.beginPath(); ctx.beginPath();
ctx!.moveTo(25 + space + i * 50, 10); ctx.moveTo(25 + space + i * 50, 10);
ctx!.lineTo(25 + space + i * 50, 140); ctx.lineTo(25 + space + i * 50, 140);
ctx!.stroke(); ctx.stroke();
}); });
ctx!.lineWidth = 1; ctx.lineWidth = 1;
this.drawDashedLine([], ctx!); this.drawDashedLine([], ctx);
this.drawDashedLine([2, 2], ctx!); this.drawDashedLine([2, 2], ctx);
this.drawDashedLine([10, 10], ctx!); this.drawDashedLine([10, 10], ctx);
this.drawDashedLine([20, 5], ctx!); this.drawDashedLine([20, 5], ctx);
this.drawDashedLine([15, 3, 3, 3], ctx!); this.drawDashedLine([15, 3, 3, 3], ctx);
this.drawDashedLine([20, 3, 3, 3, 3, 3, 3, 3], ctx!); this.drawDashedLine([20, 3, 3, 3, 3, 3, 3, 3], ctx);
ctx!.lineDashOffset = 18; ctx.lineDashOffset = 18;
this.drawDashedLine([12, 3, 3], ctx!); this.drawDashedLine([12, 3, 3], ctx);
ctx!.lineDashOffset = 0 ctx.lineDashOffset = 0
ctx!.setLineDash([0]) ctx.setLineDash([0])
ctx!!.update() ctx.update()
}, },
drawDashedLine(pattern : Array<number>, ctx : DrawableContext) { drawDashedLine(pattern : Array<number>, ctx : DrawableContext) {
ctx.beginPath(); ctx.beginPath();
...@@ -129,12 +129,12 @@ ...@@ -129,12 +129,12 @@
y += 15; y += 15;
}, },
drawCircles() { drawCircles() {
let ctx = (this.$refs['draw-circle-view'] as Element).getDrawableContext() let ctx = uni.getElementById('draw-circle-view')!.getDrawableContext()
ctx!!.reset() ctx!.reset()
// Draw shapes // Draw shapes
for (var i = 0; i < 4; i++) { for (var i = 0; i < 4; i++) {
for (var j = 0; j < 3; j++) { for (var j = 0; j < 3; j++) {
ctx!!.beginPath(); ctx.beginPath();
var x = 25 + j * 50; // x coordinate var x = 25 + j * 50; // x coordinate
var y = 25 + i * 50; // y coordinate var y = 25 + i * 50; // y coordinate
var radius = 20; // Arc radius var radius = 20; // Arc radius
...@@ -142,22 +142,22 @@ ...@@ -142,22 +142,22 @@
var endAngle = Math.PI + (Math.PI * j) / 2; // End point on circle var endAngle = Math.PI + (Math.PI * j) / 2; // End point on circle
var clockwise = i % 2 == 0 ? false : true; // clockwise or anticlockwise var clockwise = i % 2 == 0 ? false : true; // clockwise or anticlockwise
ctx!.arc(x, y, radius, startAngle, endAngle, clockwise); ctx.arc(x, y, radius, startAngle, endAngle, clockwise);
if (i > 1) { if (i > 1) {
ctx!.fill(); ctx.fill();
} else { } else {
ctx!.stroke(); ctx.stroke();
} }
} }
} }
ctx!!.update() ctx.update()
}, },
drawStar() { drawStar() {
let ctx = (this.$refs['draw-dash-line'] as Element).getDrawableContext() let ctx = uni.getElementById('draw-dash-line')!.getDrawableContext()
ctx!!.reset() ctx!.reset()
ctx!!.beginPath(); ctx.beginPath();
var horn = 5; // 画5个角 var horn = 5; // 画5个角
var angle = 360 / horn; // 五个角的度数 var angle = 360 / horn; // 五个角的度数
// 两个圆的半径 // 两个圆的半径
...@@ -169,45 +169,45 @@ ...@@ -169,45 +169,45 @@
for (var i = 0; i < horn; i++) { for (var i = 0; i < horn; i++) {
// 角度转弧度:角度/180*Math.PI // 角度转弧度:角度/180*Math.PI
// 外圆顶点坐标 // 外圆顶点坐标
ctx!.lineTo(Math.cos((18 + i * angle) / 180.0 * Math.PI) * R + x, -Math.sin((18 + i * angle) / 180.0 * Math.PI) * R + y); ctx.lineTo(Math.cos((18 + i * angle) / 180.0 * Math.PI) * R + x, -Math.sin((18 + i * angle) / 180.0 * Math.PI) * R + y);
// 內圆顶点坐标 // 內圆顶点坐标
ctx!.lineTo(Math.cos((54 + i * angle) / 180.0 * Math.PI) * r + x, -Math.sin((54 + i * angle) / 180.0 * Math.PI) * r + y); ctx.lineTo(Math.cos((54 + i * angle) / 180.0 * Math.PI) * r + x, -Math.sin((54 + i * angle) / 180.0 * Math.PI) * r + y);
} }
// closePath:关闭路径,将路径的终点与起点相连 // closePath:关闭路径,将路径的终点与起点相连
ctx!.closePath(); ctx.closePath();
ctx!.lineWidth = 3; ctx.lineWidth = 3;
ctx!.fillStyle = '#E4EF00'; ctx.fillStyle = '#E4EF00';
ctx!.strokeStyle = "red"; ctx.strokeStyle = "red";
ctx!.fill(); ctx.fill();
ctx!.stroke(); ctx.stroke();
ctx!.lineWidth = 10; ctx.lineWidth = 10;
ctx!.beginPath() ctx.beginPath()
ctx!.moveTo(170, 100) ctx.moveTo(170, 100)
ctx!.lineTo(255, 15) ctx.lineTo(255, 15)
ctx!.lineTo(340, 100) ctx.lineTo(340, 100)
ctx!.closePath() ctx.closePath()
ctx!.fill() ctx.fill()
ctx!.strokeStyle = "blue" ctx.strokeStyle = "blue"
ctx!.stroke() ctx.stroke()
ctx!.beginPath() ctx.beginPath()
ctx!.moveTo(170, 145) ctx.moveTo(170, 145)
ctx!.lineTo(255, 45) ctx.lineTo(255, 45)
ctx!.lineTo(340, 145) ctx.lineTo(340, 145)
ctx!.closePath() ctx.closePath()
ctx!.fill() ctx.fill()
ctx!.strokeStyle = "gray" ctx.strokeStyle = "gray"
ctx!.stroke() ctx.stroke()
// 未设置beginPath,导致上下表现一致,与前端一致 // 未设置beginPath,导致上下表现一致,与前端一致
ctx!.moveTo(170, 190) ctx.moveTo(170, 190)
ctx!.lineTo(255, 90) ctx.lineTo(255, 90)
ctx!.lineTo(340, 190) ctx.lineTo(340, 190)
ctx!.closePath() ctx.closePath()
ctx!.fillStyle = "orange" ctx.fillStyle = "orange"
ctx!.fill() ctx.fill()
ctx!.strokeStyle = "khaki" ctx.strokeStyle = "khaki"
ctx!.stroke() ctx.stroke()
ctx!!.update() ctx.update()
}, },
hex(num : number) : string { hex(num : number) : string {
if (num == 0) { if (num == 0) {
...@@ -226,82 +226,82 @@ ...@@ -226,82 +226,82 @@
return result return result
}, },
drawhouse() { drawhouse() {
let ctx = (this.$refs['draw-house'] as Element).getDrawableContext() let ctx = uni.getElementById('draw-house')!.getDrawableContext()
ctx!!.reset() ctx!.reset()
ctx!!.lineWidth = 10; ctx.lineWidth = 10;
// Wall // Wall
ctx!.strokeRect(75, 140, 150, 110); ctx.strokeRect(75, 140, 150, 110);
// Door // Door
ctx!.fillRect(130, 190, 40, 60); ctx.fillRect(130, 190, 40, 60);
// Roof // Roof
ctx!.beginPath(); ctx.beginPath();
ctx!.moveTo(50, 140); ctx.moveTo(50, 140);
ctx!.lineTo(150, 60); ctx.lineTo(150, 60);
ctx!.lineTo(250, 140); ctx.lineTo(250, 140);
ctx!.closePath(); ctx.closePath();
ctx!.stroke(); ctx.stroke();
ctx!!.update() ctx.update()
}, },
drawPoint() { drawPoint() {
let ctx = (this.$refs['draw-style'] as Element).getDrawableContext() let ctx = uni.getElementById('draw-style')!.getDrawableContext()
ctx!!.reset() ctx!.reset()
for (let i = 0; i < 6; i++) { for (let i = 0; i < 6; i++) {
for (let j = 0; j < 6; j++) { for (let j = 0; j < 6; j++) {
ctx!!.strokeStyle = `rgb(0,${Math.floor(255 - 42.5 * i)},${Math.floor(255 - 42.5 * j)})`; ctx.strokeStyle = `rgb(0,${Math.floor(255 - 42.5 * i)},${Math.floor(255 - 42.5 * j)})`;
ctx!.beginPath(); ctx.beginPath();
ctx!.arc(12.5 + j * 25, 12.5 + i * 25, 10, 0, Math.PI * 2, true); ctx.arc(12.5 + j * 25, 12.5 + i * 25, 10, 0, Math.PI * 2, true);
ctx!.stroke(); ctx.stroke();
} }
} }
for (let i = 0; i < 6; i++) { for (let i = 0; i < 6; i++) {
for (let j = 0; j < 6; j++) { for (let j = 0; j < 6; j++) {
ctx!!.fillStyle = `rgb(${Math.floor(255 - 42.5 * i)},${Math.floor(255 - 42.5 * j)},0)`; ctx.fillStyle = `rgb(${Math.floor(255 - 42.5 * i)},${Math.floor(255 - 42.5 * j)},0)`;
ctx!.fillRect(180 + j * 25, i * 25, 25, 25); ctx.fillRect(180 + j * 25, i * 25, 25, 25);
} }
} }
ctx!!.update() ctx.update()
}, },
drawRect() { drawRect() {
let ctx = (this.$refs['draw-odd'] as Element).getDrawableContext() let ctx = uni.getElementById('draw-odd')!.getDrawableContext()
ctx!!.reset() ctx!.reset()
// Create path // Create path
ctx!!.moveTo(30, 90); ctx.moveTo(30, 90);
ctx!.lineTo(110, 20); ctx.lineTo(110, 20);
ctx!.lineTo(240, 130); ctx.lineTo(240, 130);
ctx!.lineTo(60, 130); ctx.lineTo(60, 130);
ctx!.lineTo(190, 20); ctx.lineTo(190, 20);
ctx!.lineTo(270, 90); ctx.lineTo(270, 90);
ctx!.closePath(); ctx.closePath();
// Fill path // Fill path
ctx!.fillStyle = "green"; ctx.fillStyle = "green";
ctx!.fill("evenodd"); ctx.fill("evenodd");
ctx!!.update() ctx.update()
}, },
drawArcTo() { drawArcTo() {
let ctx = (this.$refs['draw-arcto'] as Element).getDrawableContext() let ctx = uni.getElementById('draw-arcto')!.getDrawableContext()
ctx!.reset() ctx!.reset()
ctx!.beginPath(); ctx.beginPath();
ctx!.moveTo(50, 20); ctx.moveTo(50, 20);
ctx!.bezierCurveTo(230, 30, 150, 60, 50, 100); ctx.bezierCurveTo(230, 30, 150, 60, 50, 100);
ctx!.stroke(); ctx.stroke();
ctx!.fillStyle = "blue"; ctx.fillStyle = "blue";
// start point // start point
ctx!.fillRect(50, 20, 10, 10); ctx.fillRect(50, 20, 10, 10);
// end point // end point
ctx!.fillRect(50, 100, 10, 10); ctx.fillRect(50, 100, 10, 10);
ctx!.fillStyle = "red"; ctx.fillStyle = "red";
// control point one // control point one
ctx!.fillRect(230, 30, 10, 10); ctx.fillRect(230, 30, 10, 10);
// control point two // control point two
ctx!.fillRect(150, 70, 10, 10); ctx.fillRect(150, 70, 10, 10);
ctx!.update() ctx.update()
} }
} }
} }
......
const PAGE_PATH = "/pages/API/element-takesnapshot/element-takesnapshot";
describe("element-takesnapshot", () => {
let page;
function getData(key = '') {
return new Promise(async (resolve, reject) => {
const data = await page.data()
resolve(key ? data[key] : data)
})
}
beforeAll(async () => {
page = await program.reLaunch(PAGE_PATH)
await page.waitFor(600);
});
it("takeSnapshot", async () => {
await page.waitFor(600)
let btnTakeSnapshot = await page.$('.btn-TakeSnapshot')
await btnTakeSnapshot.tap()
page.waitFor(600)
const image = await getData('snapImage')
console.log(image)
///storage/emulated/0/Android/data/io.dcloud.uniappx/apps/__UNI__3584C99/cache/temp/screenshot/1697513148915.png
expect(image.length).toBeGreaterThan(20)
});
});
<template>
<view>
<page-head id="page-head" title="getElementById"></page-head>
<view class="uni-padding-wrap" id="snapshot-content">
<text id="text">this is text</text>
<view id="view" class="uni-common-mt" style="border: 1px solid red">this is view</view>
</view>
<button class="uni-btn" @click="changeViewStyle">
修改 view 宽高及背景色
</button>
<button class="uni-btn btn-TakeSnapshot" type="primary" @tap="takeSnapshotClick">
点击截图
</button>
<image style="margin-top: 20px;" :src="snapImage" mode="aspectFit" @longpress="saveToAlbum"></image>
</view>
</template>
<script lang="uts">
export default {
data() {
return {
snapImage: "/static/uni.png"
}
},
methods: {
changeViewStyle() {
const text = uni.getElementById('text')!
text.style.setProperty('color', 'red')
const view = uni.getElementById('view')!
view.style.setProperty('width', '90%')
view.style.setProperty('height', '50px')
view.style.setProperty('backgroundColor', '#007AFF')
},
takeSnapshotClick() {
const view = uni.getElementById('snapshot-content')!
view.takeSnapshot({
success: function (res) {
console.log(res.tempFilePath)
this.snapImage = res.tempFilePath
uni.showToast({
title: '截图成功,路径:' + res.tempFilePath,
icon: "none"
})
},
fail: function (res) {
console.log(res)
uni.showToast({
icon: 'error',
title: '截图失败'
})
}
})
},
saveToAlbum(e : TouchEvent) {
// console.log(e.currentTarget!.getAttribute("src"));
let filePath : string = e.currentTarget!.getAttribute("src") as string
uni.showActionSheet({
itemList: ["保存"],
success: res => {
// console.log(res.tapIndex);
if (res.tapIndex == 0) {
uni.saveImageToPhotosAlbum({
filePath: filePath,
success() {
uni.showToast({
position: "center",
icon: "none",
title: "图片保存成功,请到手机相册查看"
})
},
fail(e) {
uni.showModal({
content: "保存相册失败,errCode:" + e.errCode + ",errMsg:" + e.errMsg + ",errSubject:" + e.errSubject,
showCancel: false
});
}
})
}
},
fail: () => { },
complete: () => { }
});
}
}
}
</script>
...@@ -18,7 +18,11 @@ ...@@ -18,7 +18,11 @@
scrollData: [] as Array<string>, scrollData: [] as Array<string>,
size_enum: [{ "value": 0, "name": "item---0" }, { "value": 3, "name": "item---3" }] as ItemType[], size_enum: [{ "value": 0, "name": "item---0" }, { "value": 3, "name": "item---3" }] as ItemType[],
scrollIntoView: "", scrollIntoView: "",
refresherrefresh: false refresherrefresh: false,
refresher_default_style_input: "black",
text: ['继续下拉执行刷新', '释放立即刷新', '刷新中', ""],
state: 3,
reset: true
} }
}, },
onLoad() { onLoad() {
...@@ -36,17 +40,30 @@ ...@@ -36,17 +40,30 @@
list_view_touchend() { console.log("手指触摸动作结束") }, list_view_touchend() { console.log("手指触摸动作结束") },
list_view_tap() { console.log("手指触摸后马上离开") }, list_view_tap() { console.log("手指触摸后马上离开") },
list_view_longpress() { console.log("如果一个组件被绑定了 longpress 事件,那么当用户长按这个组件时,该事件将会被触发。") }, list_view_longpress() { console.log("如果一个组件被绑定了 longpress 事件,那么当用户长按这个组件时,该事件将会被触发。") },
list_view_refresherpulling() { console.log("下拉刷新控件被下拉") }, list_view_refresherpulling(e : RefresherEvent) {
console.log("下拉刷新控件被下拉")
if(this.reset) {
if(e.detail.dy > 45) {
this.state = 1
} else {
this.state = 0
}
}
},
list_view_refresherrefresh() { list_view_refresherrefresh() {
console.log("下拉刷新被触发 ") console.log("下拉刷新被触发 ")
this.refresherrefresh = true this.refresherrefresh = true
this.refresher_triggered_boolean = true this.refresher_triggered_boolean = true
this.state = 2
this.reset = false;
setTimeout(function(){ setTimeout(function(){
this.refresher_triggered_boolean = false this.refresher_triggered_boolean = false
}, 1500) }, 1500)
}, },
list_view_refresherrestore() { list_view_refresherrestore() {
this.refresherrefresh = false this.refresherrefresh = false
this.state = 3
this.reset = true
console.log("下拉刷新被复位") console.log("下拉刷新被复位")
}, },
list_view_refresherabort() { console.log("下拉刷新被中止") }, list_view_refresherabort() { console.log("下拉刷新被中止") },
...@@ -90,6 +107,13 @@ ...@@ -90,6 +107,13 @@
return true return true
} }
return false return false
},
change_refresher_style_boolean(checked : boolean) {
if(checked) {
this.refresher_default_style_input = "none"
} else {
this.refresher_default_style_input = "black"
}
} }
} }
} }
...@@ -102,6 +126,7 @@ ...@@ -102,6 +126,7 @@
:scroll-left="scroll_left_input" :show-scrollbar="show_scrollbar_boolean" :scroll-into-view="scrollIntoView" :scroll-left="scroll_left_input" :show-scrollbar="show_scrollbar_boolean" :scroll-into-view="scrollIntoView"
:scroll-with-animation="scroll_with_animation_boolean" :refresher-enabled="refresher_enabled_boolean" :scroll-with-animation="scroll_with_animation_boolean" :refresher-enabled="refresher_enabled_boolean"
:refresher-background="refresher_background_input" :refresher-triggered="refresher_triggered_boolean" :refresher-background="refresher_background_input" :refresher-triggered="refresher_triggered_boolean"
:refresher-default-style="refresher_default_style_input"
@click="list_view_click" @touchstart="list_view_touchstart" @touchmove="list_view_touchmove" @click="list_view_click" @touchstart="list_view_touchstart" @touchmove="list_view_touchmove"
@touchcancel="list_view_touchcancel" @touchend="list_view_touchend" @tap="list_view_tap" @touchcancel="list_view_touchcancel" @touchend="list_view_touchend" @tap="list_view_tap"
@longpress="list_view_longpress" @refresherpulling="list_view_refresherpulling" @longpress="list_view_longpress" @refresherpulling="list_view_refresherpulling"
...@@ -115,6 +140,9 @@ ...@@ -115,6 +140,9 @@
class="list-item"> class="list-item">
<text>{{key}}</text> <text>{{key}}</text>
</list-item> </list-item>
<list-item slot="refresher" class="refresh-box">
<text class="tip-text">{{text[state]}}</text>
</list-item>
</list-view> </list-view>
</view> </view>
...@@ -125,6 +153,7 @@ ...@@ -125,6 +153,7 @@
<boolean-data :defaultValue="false" title="设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发" <boolean-data :defaultValue="false" title="设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发"
@change="change_refresher_triggered_boolean"></boolean-data> @change="change_refresher_triggered_boolean"></boolean-data>
<boolean-data :defaultValue="false" title="开启下拉刷新" @change="change_refresher_enabled_boolean"></boolean-data> <boolean-data :defaultValue="false" title="开启下拉刷新" @change="change_refresher_enabled_boolean"></boolean-data>
<boolean-data :defaultValue="false" title="开启自定义样式" @change="change_refresher_style_boolean"></boolean-data>
<boolean-data :defaultValue="false" title="是否在设置滚动条位置时使用滚动动画,设置false没有滚动动画" <boolean-data :defaultValue="false" title="是否在设置滚动条位置时使用滚动动画,设置false没有滚动动画"
@change="change_scroll_with_animation_boolean"></boolean-data> @change="change_scroll_with_animation_boolean"></boolean-data>
<boolean-data :defaultValue="true" title="控制是否出现滚动条" @change="change_show_scrollbar_boolean"></boolean-data> <boolean-data :defaultValue="true" title="控制是否出现滚动条" @change="change_show_scrollbar_boolean"></boolean-data>
...@@ -163,4 +192,17 @@ ...@@ -163,4 +192,17 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.tip-text {
color: #888;
font-size: 12px;
}
.refresh-box {
justify-content: center;
align-items: center;
flex-direction: row;
height: 45px;
width: 100%;
}
</style> </style>
...@@ -45,16 +45,16 @@ ...@@ -45,16 +45,16 @@
// this.sliderValue = value // this.sliderValue = value
// TODO 跳过vue框架,直接修改原生组件 // TODO 跳过vue框架,直接修改原生组件
(this.$refs["slider1"]! as SliderElement[]).forEach((item) => { (this.$refs["slider1"]! as UniSliderElement[]).forEach((item) => {
item.value = value item.value = value
}); });
(this.$refs["slider2"]! as SliderElement[]).forEach((item) => { (this.$refs["slider2"]! as UniSliderElement[]).forEach((item) => {
item.value = value item.value = value
}); });
(this.$refs["slider3"]! as SliderElement[]).forEach((item) => { (this.$refs["slider3"]! as UniSliderElement[]).forEach((item) => {
item.value = value item.value = value
}); });
(this.$refs["slider4"]! as SliderElement[]).forEach((item) => { (this.$refs["slider4"]! as UniSliderElement[]).forEach((item) => {
item.value = value item.value = value
}); });
} }
......
describe('component-native-sticky-header', () => {
let page
beforeAll(async () => {
page = await program.reLaunch('/pages/component/sticky-header/sticky-header')
await page.waitFor(200)
})
//检测吸顶效果
it('check_sticky_header', async () => {
await page.callMethod('confirm_scroll_top_input', 600)
await page.waitFor(400)
const image = await program.screenshot();
expect(image).toMatchImageSnapshot();
})
})
<template>
<list-view :scroll-y="true" class="page" rebound="false" :scroll-top="scroll_top_input" :refresher-enabled="refresher_enabled_boolean"
:refresher-triggered="refresher_triggered_boolean" @refresherrefresh="list_view_refresherrefresh">
<list-item type = 1>
<swiper indicator-dots="true" circular="true">
<swiper-item v-for="i in 3" :item-id="i">
<image src="/static/shuijiao.jpg" style="height: 240px;"></image>
<text style="position: absolute;">{{i}}</text>
</swiper-item>
</swiper>
</list-item>
<list-item class="content-item" type = 2>
<text class="text">向上滑动页面,体验sticky-header吸顶效果。</text>
</list-item>
<sticky-header>
<scroll-view style="background-color: #f5f5f5; flex-direction: row;" :scroll-x="true" :scroll-y="false" :show-scrollbar="false">
<view class="flex-row" style="align-self: flex-start; flex-direction: row;">
<text ref="swipertab" class="sift-item"
v-for="(name,index) in sift_item" @click="clickTH(index)">
{{name}}
</text>
</view>
</scroll-view>
</sticky-header>
<list-item v-for="(item,index) in list_item" :key="index" class="content-item" type = 3>
<text class="text">{{item}}</text>
</list-item>
</list-view>
</template>
<script>
export default {
data() {
return {
sift_item: ["排序", "筛选"],
list_item: [] as Array<string>,
refresher_enabled_boolean: true,
refresher_triggered_boolean: false,
scroll_top_input: 0
}
},
onLoad() {
let lists : Array<string> = []
for (let i = 0; i < 40; i++) {
lists.push("item---" + i)
}
this.list_item = lists
},
methods: {
list_view_refresherrefresh() {
console.log("下拉刷新被触发 ")
this.refresher_triggered_boolean = true
setTimeout(function(){
this.refresher_triggered_boolean = false
}, 1500)
},
confirm_scroll_top_input(value : number) {
this.scroll_top_input = value
},
clickTH(index:number){
console.log("点击表头:" + index);
}
}
}
</script>
<style>
.page {
flex: 1;
background-color: #f5f5f5;
}
.content-item {
padding: 15px;
margin: 5px 0;
background-color: #fff;
}
.text {
font-size: 14px;
color: #666;
line-height: 20px;
}
.sift-item {
color: #555;
font-size: 16px;
padding: 12px 15px;
}
</style>
<template> <template>
<view> <view>
<page-head :title="title"></page-head> <page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt"> <view class="uni-padding-wrap uni-common-mt">
<view class="text-box" scroll-y="true"> <view class="text-box" scroll-y="true">
<text class="text">{{text}}</text> <text class="text">{{ text }}</text>
</view> </view>
<view class="uni-btn-v"> <view class="uni-btn-v">
<button class="uni-btn" type="primary" :disabled="!canAdd" @click="add">add line</button> <button class="uni-btn" type="primary" :disabled="!canAdd" @click="add">
<button class="uni-btn" type="warn" :disabled="!canRemove" @click="remove">remove line</button> add line
<button class="uni-btn" type="primary" @click="textProps">更多属性示例</button> </button>
</view> <button
</view> class="uni-btn"
type="warn"
:disabled="!canRemove"
@click="remove"
>
remove line
</button>
<button class="uni-btn" type="primary" @click="textProps">
更多属性示例
</button>
</view>
</view> </view>
</view>
</template> </template>
<script lang="uts"> <script lang="uts">
export default { export default {
data() { data() {
return { return {
title: 'text', title: 'text',
texts: [ texts: [
'HBuilderX,轻巧、极速,极客编辑器', 'HBuilderX,轻巧、极速,极客编辑器',
'uni-app x,终极跨平台方案', 'uni-app x,终极跨平台方案',
'uniCloud,js serverless云服务', 'uniCloud,js serverless云服务',
'uts,大一统语言', 'uts,大一统语言',
'uniMPSdk,让你的App具备小程序能力', 'uniMPSdk,让你的App具备小程序能力',
'uni-admin,开源、现成的全端管理后台', 'uni-admin,开源、现成的全端管理后台',
'uni-id,开源、全端的账户中心', 'uni-id,开源、全端的账户中心',
'uni-pay,开源、云端一体、全平台的支付', 'uni-pay,开源、云端一体、全平台的支付',
'uni-ai,聚合ai能力', 'uni-ai,聚合ai能力',
'uni-cms,开源、云端一体、全平台的内容管理平台', 'uni-cms,开源、云端一体、全平台的内容管理平台',
'uni-im,开源、云端一体、全平台的im即时消息', 'uni-im,开源、云端一体、全平台的im即时消息',
'uni统计,开源、完善、全平台的统计报表', 'uni统计,开源、完善、全平台的统计报表',
'......' '......'
] as string[], ] as string[],
text: '', text: '',
canAdd: true, canAdd: true,
canRemove: false, canRemove: false,
extraLine: [] as string[] extraLine: [] as string[]
} }
},
methods: {
add: function () {
this.extraLine.push(this.texts[this.extraLine.length % 12]);
this.text = this.extraLine.join('\n');
this.canAdd = this.extraLine.length < 12;
this.canRemove = this.extraLine.length > 0;
}, },
methods: { remove: function () {
add: function () { if (this.extraLine.length > 0) {
this.extraLine.push(this.texts[this.extraLine.length % 12]); this.extraLine.pop();
this.text = this.extraLine.join('\n'); this.text = this.extraLine.join('\n');
this.canAdd = this.extraLine.length < 12; this.canAdd = this.extraLine.length < 12;
this.canRemove = this.extraLine.length > 0; this.canRemove = this.extraLine.length > 0;
}, }
remove: function () { },
if (this.extraLine.length > 0) { textProps: function () {
this.extraLine.pop(); uni.navigateTo({
this.text = this.extraLine.join('\n'); url: '/pages/component/text/text-props'
this.canAdd = this.extraLine.length < 12; })
this.canRemove = this.extraLine.length > 0; }
}
},
textProps: function () {
uni.navigateTo({
url: '/pages/component/text/text-props'
})
}
}
} }
}
</script> </script>
<style> <style>
.text-box { .text-box {
margin-bottom: 40rpx; margin-bottom: 40rpx;
padding: 40rpx 0; padding: 40rpx 0;
display: flex; display: flex;
min-height: 300rpx; min-height: 300rpx;
background-color: #FFFFFF; background-color: #ffffff;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.text { .text {
font-size: 30rpx; font-size: 30rpx;
color: #353535; color: #353535;
line-height: 54rpx; line-height: 54rpx;
text-align: center; text-align: center;
} }
</style> </style>
\ No newline at end of file
<template>
<view class="page">
<unicloud-db ref="udb" v-slot:default="{data, loading, error}" :collection="collection" loadtime="manual">
<view v-if="error" class="error">{{error}}</view>
</unicloud-db>
<view class="form-item">
<text class="form-item-label">姓名</text>
<input class="form-item-input" placeholder="姓名" v-model="username" />
</view>
<view class="form-item">
<text class="form-item-label">电话</text>
<input class="form-item-input" placeholder="电话" v-model="mobile" />
</view>
<view class="form-item">
<text class="form-item-label">邮箱</text>
<input class="form-item-input" placeholder="邮箱地址" v-model="email" />
</view>
<view class="form-item">
<text class="form-item-label">备注</text>
<textarea class="form-item-input" placeholder="备注" v-model="comment" />
</view>
<view class="form-item">
<text class="form-item-label">性别</text>
<radio-group class="radio-list" @change="radioChange">
<view class="radio-item" v-for="(item, _) in genderList" :key="item.value">
<radio :value="item.value" :checked="item.value == gender" />
<text>{{item.text}}</text>
</view>
</radio-group>
</view>
<button class="btn-add" type="primary" @click="submit">保存</button>
</view>
</template>
<script>
import { COLLECTION_NAME, GenderType, GenderList, UNICLOUD_DB_CONTACTS_ADD } from './types.uts'
export default {
data() {
return {
collection: COLLECTION_NAME,
username: "",
mobile: "",
gender: "",
comment: "",
email: "",
genderList: GenderList as GenderType[],
$uniCloudElement: null as UniCloudDBElement | null
}
},
onReady() {
this.$uniCloudElement = this.$refs['udb'] as UniCloudDBElement
},
methods: {
radioChange(e : RadioGroupChangeEvent) {
this.gender = e.detail.value
},
submit() {
const value = {
username: this.username,
gender: parseInt(this.gender),
mobile: this.mobile,
comment: this.comment,
email: this.email,
};
this.$uniCloudElement!.add(value, {
showToast: false,
needLoading: true,
loadingTitle: "正在保存...",
success: (_ : UniCloudDBAddResult) => {
// TODO 后续通过 EventChannel 实现
uni.$emit(UNICLOUD_DB_CONTACTS_ADD, '')
setTimeout(() => {
uni.navigateBack()
}, 500)
},
fail: (err : any | null) => {
const error = err as UniCloudError
uni.showModal({
content: error.errMsg,
showCancel: false
})
}
})
}
}
}
</script>
<style>
.page {
padding: 15px;
}
.form-item {
flex-direction: row;
margin-bottom: 15px;
align-items: center;
}
.form-item-label {
width: 45px;
margin-right: 10px;
}
.form-item-input {
flex: 1;
font-size: 14px;
color: #666;
border: 1px #e5e5e5 solid;
border-radius: 5px;
padding: 8px;
}
.radio-list {
flex-direction: row;
}
.radio-item {
flex-direction: row;
margin-right: 30px;
align-items: center;
}
.btn-add {
margin-top: 50px;
}
</style>
\ No newline at end of file
<template>
<scroll-view class="page">
<unicloud-db ref="udb" v-slot:default="{data, loading, error}" :collection="collection" :where="where"
loadtime="manual" page-data="replace">
<view v-if="error!=null" class="error">{{error.errMsg}}</view>
<view v-if="loading" class="loading">正在加载...</view>
<view v-if="data.length>0">
<view class="form-item">
<text class="form-item-label">姓名</text>
<text class="form-item-input">{{data[0]['username']}}</text>
</view>
<view class="form-item">
<text class="form-item-label">电话</text>
<text class="form-item-input">{{data[0]['mobile']}}</text>
</view>
<view class="form-item">
<text class="form-item-label">邮箱</text>
<text class="form-item-input">{{data[0]['email']}}</text>
</view>
<view class="form-item">
<text class="form-item-label">备注</text>
<text class="form-item-input">{{data[0]['comment']}}</text>
</view>
<view class="form-item">
<text class="form-item-label">性别</text>
<text class="form-item-input">{{displayGender(data[0]['gender'])}}</text>
</view>
<button class="btn-update" type="default" @click="gotoUpdatePage(data[0].getString('_id'))">编辑</button>
</view>
</unicloud-db>
</scroll-view>
</template>
<script>
import { COLLECTION_NAME, GenderType, GenderList, UNICLOUD_DB_CONTACTS_UPDATE } from './types.uts'
export default {
data() {
return {
collection: COLLECTION_NAME,
where: '',
$whereID: '',
$uniCloudElement: null as UniCloudDBElement | null
}
},
onLoad(options : Map<string, string>) {
this.$whereID = options['id'] as string;
this.where = `_id=='${this.$whereID}'`;
},
onShow() {
// TODO 后续通过 EventChannel 实现
uni.$off(UNICLOUD_DB_CONTACTS_UPDATE, this.onDataChange);
},
onUnload() {
// TODO 后续通过 EventChannel 实现
uni.$off(UNICLOUD_DB_CONTACTS_UPDATE, this.onDataChange);
},
onReady() {
this.$uniCloudElement = this.$refs['udb'] as UniCloudDBElement
this.$uniCloudElement!.loadData()
},
methods: {
displayGender(value : any | null) : string {
const str = (value ?? 0).toString()
return (GenderList as GenderType[]).find((item : GenderType) : boolean => {
return item.value == str
})!.text;
},
gotoUpdatePage(id : string | null) {
// TODO 后续通过 EventChannel 实现
uni.$on(UNICLOUD_DB_CONTACTS_UPDATE, this.onDataChange);
uni.navigateTo({
url: './edit?id=' + id
})
},
onDataChange(id : string) {
this.$uniCloudElement!.loadData()
}
}
}
</script>
<style>
.page {
padding: 15px;
}
.loading {
align-items: center;
}
.form-item {
flex-direction: row;
margin-bottom: 15px;
align-items: center;
padding: 8px 0;
}
.form-item-label {
width: 45px;
margin-right: 10px;
}
.form-item-input {
flex: 1;
font-size: 14px;
color: #666;
}
</style>
<template>
<view class="page">
<navbar>
<template v-slot:left>
<text class="btn-cancel">取消</text>
</template>
<template v-slot:right>
<text class="btn-update" @click="update">保存</text>
</template>
</navbar>
<scroll-view class="scroll-view" :scroll-y="true">
<unicloud-db ref="udb" v-slot:default="{data, loading, error}" :collection="collection" :where="where"
page-data="replace" loadtime="manual" @load="onQueryLoad">
<view v-if="error!=null" class="error">{{error.errMsg}}</view>
<view v-if="loading" class="loading">正在加载...</view>
<view v-if="data.length>0">
<view class="form-item">
<text class="form-item-label">姓名</text>
<input class="form-item-input" placeholder="姓名" v-model="username" />
</view>
<view class="form-item">
<text class="form-item-label">电话</text>
<input class="form-item-input" placeholder="电话" v-model="mobile" />
</view>
<view class="form-item">
<text class="form-item-label">邮箱</text>
<input class="form-item-input" placeholder="邮箱地址" v-model="email" />
</view>
<view class="form-item">
<text class="form-item-label">备注</text>
<textarea class="form-item-input" placeholder="备注" v-model="comment" />
</view>
<view class="form-item">
<text class="form-item-label">性别</text>
<radio-group class="radio-list" @change="radioChange">
<view class="radio-item" v-for="(item, _) in genderList" :key="item.value">
<radio :value="item.value" :checked="item.value == gender" />
<text>{{item.text}}</text>
</view>
</radio-group>
</view>
<button class="btn-delete" type="warn"
@click="remove(data[0].getString('_id'), data[0].getString('username'))">删除联系人</button>
</view>
</unicloud-db>
</scroll-view>
</view>
</template>
<script>
import { COLLECTION_NAME, GenderType, GenderList, UNICLOUD_DB_CONTACTS_UPDATE, UNICLOUD_DB_CONTACTS_DELETE } from './types.uts'
import navbar from './navbar.uvue'
export default {
components: {
navbar
},
data() {
return {
collection: COLLECTION_NAME,
where: '',
username: "",
mobile: "",
gender: '',
comment: "",
email: "",
genderList: GenderList as GenderType[],
$whereID: '',
$uniCloudElement: null as UniCloudDBElement | null
}
},
onLoad(options : Map<string, string>) {
this.$whereID = options['id'] as string;
this.where = `_id=='${this.$whereID}'`;
},
onReady() {
this.$uniCloudElement = this.$refs['udb'] as UniCloudDBElement
this.$uniCloudElement!.loadData()
},
methods: {
radioChange(e : RadioGroupChangeEvent) {
this.gender = e.detail.value
},
update() {
const value = {
username: this.username,
gender: parseInt(this.gender),
mobile: this.mobile,
comment: this.comment,
email: this.email,
};
this.$uniCloudElement!.update(this.$whereID, value, {
showToast: false,
needLoading: true,
needConfirm: false,
loadingTitle: "正在保存...",
success: (_ : UniCloudDBUpdateResult) => {
// TODO 后续通过 EventChannel 实现
uni.$emit(UNICLOUD_DB_CONTACTS_UPDATE, this.$whereID)
setTimeout(() => {
uni.navigateBack()
}, 500)
},
fail: (err : any | null) => {
const error = err as UniCloudError
uni.showModal({
content: error.errMsg,
showCancel: false
})
}
})
},
remove(id : string | null, name : string | null) {
this.$uniCloudElement!.remove(id!, {
needConfirm: true,
needLoading: true,
loadingTitle: "正在删除...",
confirmTitle: "确定删除?",
confirmContent: name,
success: (_ : UniCloudDBRemoveResult) => {
// TODO 后续通过 EventChannel 实现
uni.$emit(UNICLOUD_DB_CONTACTS_DELETE, this.$whereID)
setTimeout(() => {
uni.navigateBack({
delta: 2
})
}, 500)
},
fail: (err : any | null) => {
const error = err as UniCloudError
uni.showModal({
content: error.errMsg,
showCancel: false
})
}
})
},
onQueryLoad(data : Array<UTSJSONObject>, _ : boolean) {
if (data.length == 0) {
return
}
const data1 = data[0];
this.username = data1.getString('username') ?? "";
this.mobile = data1.getString('mobile') ?? "";
this.gender = data1.getNumber('gender')?.toString() ?? '0';
this.comment = data1.getString('comment') ?? "";
this.email = data1.getString('email') ?? "";
}
}
}
</script>
<style>
.page {
flex: 1;
}
.scroll-view {
padding: 15px;
flex: 1;
}
.loading {
align-items: center;
}
.form-item {
flex-direction: row;
margin-bottom: 15px;
align-items: center;
}
.form-item-label {
width: 45px;
margin-right: 10px;
}
.form-item-input {
flex: 1;
font-size: 14px;
color: #666;
border: 1px #e5e5e5 solid;
border-radius: 5px;
padding: 8px;
}
.radio-list {
flex-direction: row;
}
.radio-item {
flex-direction: row;
margin-right: 30px;
align-items: center;
}
.btn-cancel {
color: #fff;
margin-left: 15px;
}
.btn-update {
color: #fff;
margin-right: 15px;
}
.btn-delete {
margin-top: 350px;
}
</style>
<template>
<view class="page">
<unicloud-db ref="udb" v-slot:default="{data, pagination, loading, hasMore, error}" :collection="collection"
:page-size="10" :getcount="true" loadtime="manual">
<view v-if="error!=null" class="error">{{error.errMsg}}</view>
<list-view ref="listView" class="list-view" :scroll-y="true" @scrolltolower="loadMore()">
<list-item class="list-item" v-for="(item, _) in data" @click="gotoDetailPage(item['_id'] as string)">
<view class="list-item-fill">
<text class="name">{{item['username']}}</text>
<text class="mobile">{{item['mobile']}}</text>
</view>
</list-item>
</list-view>
<view v-if="loading" class="loading">正在加载...</view>
<view v-if="data.length>0" class="pagination">
<text class="pagination-item">{{data.length}} / {{pagination.count}}</text>
</view>
</unicloud-db>
<view class="btn-plus" @click="gotoAddPage">
<text class="btn-plus-text">+</text>
</view>
</view>
</template>
<script>
import { COLLECTION_NAME, UNICLOUD_DB_CONTACTS_ADD, UNICLOUD_DB_CONTACTS_UPDATE, UNICLOUD_DB_CONTACTS_DELETE } from './types.uts'
export default {
data() {
return {
collection: COLLECTION_NAME,
$uniCloudElement: null as UniCloudDBElement | null
}
},
onReady() {
// TODO 后续通过 EventChannel 实现
uni.$on(UNICLOUD_DB_CONTACTS_DELETE, this.onDataChange);
this.$uniCloudElement = this.$refs['udb'] as UniCloudDBElement
this.$uniCloudElement!.loadData()
},
onUnload() {
// TODO 后续通过 EventChannel 实现
uni.$off(UNICLOUD_DB_CONTACTS_ADD, this.onDataChange);
uni.$off(UNICLOUD_DB_CONTACTS_UPDATE, this.onDataChange);
uni.$off(UNICLOUD_DB_CONTACTS_DELETE, this.onDataChange);
},
onShow() {
// TODO 后续通过 EventChannel 实现
uni.$off(UNICLOUD_DB_CONTACTS_ADD, this.onDataChange);
uni.$off(UNICLOUD_DB_CONTACTS_UPDATE, this.onDataChange);
},
onPullDownRefresh() {
this.$uniCloudElement!.loadData({
clear: true,
success: (_ : UniCloudDBGetResult) => {
uni.stopPullDownRefresh()
}
})
},
methods: {
loadMore() {
this.$uniCloudElement!.loadMore()
},
gotoAddPage() {
// TODO 后续通过 EventChannel 实现
uni.$on(UNICLOUD_DB_CONTACTS_ADD, this.onDataChange);
uni.navigateTo({
url: './add'
})
},
gotoDetailPage(id : string) {
// TODO 后续通过 EventChannel 实现
uni.$on(UNICLOUD_DB_CONTACTS_UPDATE, this.onDataChange);
uni.navigateTo({
url: './detail?id=' + id
})
},
onDataChange(id : string) {
this.$uniCloudElement!.loadData({
clear: true
})
}
}
}
</script>
<style>
.page {
flex: 1;
flex-direction: column;
}
.loading {
align-items: center;
padding: 20px;
}
.list-view {
flex: 1;
flex-direction: column;
}
.list-item {
flex-direction: row;
padding: 10px;
background-color: #fff;
margin-bottom: 1px;
}
.mobile {
margin-top: 5px;
}
.btn-plus {
position: absolute;
width: 64px;
height: 64px;
right: 20px;
bottom: 20px;
align-items: center;
justify-content: center;
background-color: #1e90ff;
border-radius: 64px;
}
.btn-plus-text {
font-size: 30px;
color: #fff;
}
.pagination {
align-items: center;
background-color: #f8f8f8;
padding: 15px;
}
</style>
<template>
<view class="navigation-bar">
<view :style="statusBarStyle"></view>
<view class="navigation-bar-header">
<view class="navbar-left" @click="back">
<slot name="left">1</slot>
</view>
<view class="navbar-content">
<slot name="middle"></slot>
</view>
<view class="navbar-right">
<slot name="right"></slot>
</view>
</view>
</view>
</template>
<script>
export default {
name: "navbar",
props: {
},
data() {
return {
statusBarHeight: 0
};
},
computed: {
statusBarStyle() : string {
return `padding-top:${this.statusBarHeight}px`
},
},
created() {
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
setTimeout(() => {
uni.setNavigationBarColor({
frontColor: '#ffffff',
backgroundColor: '#007AFF'
})
}, 100)
},
methods: {
back() {
uni.navigateBack({})
}
}
}
</script>
<style>
.navigation-bar {
background-color: #007AFF;
flex-direction: column;
}
.navigation-bar-header {
position: relative;
flex-direction: row;
align-items: center;
height: 45px;
}
.navbar-content {
flex: 1;
align-items: center;
}
</style>
export const COLLECTION_NAME = 'opendb-contacts'
export type GenderType = {
text : string,
value : string,
}
export const GenderList = [
{
text: "未知",
value: "0"
},
{
text: "男",
value: "1"
},
{
text: "女",
value: "2"
},
] as GenderType[]
export const UNICLOUD_DB_CONTACTS_ADD = 'unicloud-db-contacts-add'
export const UNICLOUD_DB_CONTACTS_UPDATE = 'unicloud-db-contacts-update'
export const UNICLOUD_DB_CONTACTS_DELETE = 'unicloud-db-contacts-delete'
...@@ -12,9 +12,6 @@ ...@@ -12,9 +12,6 @@
<boolean-data :defaultValue="false" title="是否阻止本节点的祖先节点出现点击态" @change="change_stop_propagation_boolean"></boolean-data> <boolean-data :defaultValue="false" title="是否阻止本节点的祖先节点出现点击态" @change="change_stop_propagation_boolean"></boolean-data>
<enum-data :items="start_time_enum" title="按住后多久出现点击态" @change="radio_change_start_time_enum"></enum-data> <enum-data :items="start_time_enum" title="按住后多久出现点击态" @change="radio_change_start_time_enum"></enum-data>
<enum-data :items="stay_time_enum" title="手指松开后点击态保留时间" @change="radio_change_stay_time_enum"></enum-data> <enum-data :items="stay_time_enum" title="手指松开后点击态保留时间" @change="radio_change_stay_time_enum"></enum-data>
<view class="uni-padding-wrap uni-common-mt uni-common-mb">
<button class="uni-common-mt" @click="goGeneralAttribute('/pages/component/view/view-draw')">DrawableContext</button>
</view>
</view> </view>
<!-- #ifdef APP --> <!-- #ifdef APP -->
</scroll-view> </scroll-view>
...@@ -46,11 +43,6 @@ export default { ...@@ -46,11 +43,6 @@ export default {
radio_change_stay_time_enum(time : number) { radio_change_stay_time_enum(time : number) {
this.stay_time = time this.stay_time = time
}, },
goGeneralAttribute(path: string) {
uni.navigateTo({
url: path,
})
},
}, },
} }
</script> </script>
......
...@@ -34,7 +34,6 @@ const pages = [ ...@@ -34,7 +34,6 @@ const pages = [
'/pages/component/text/text', '/pages/component/text/text',
'/pages/component/textarea/textarea', '/pages/component/textarea/textarea',
// '/pages/component/video/video', // '/pages/component/video/video',
'/pages/component/view/view-draw',
'/pages/component/view/view', '/pages/component/view/view',
// '/pages/component/web-view/web-view', // 动态内容 // '/pages/component/web-view/web-view', // 动态内容
'/pages/component/web-view-local/web-view-local', '/pages/component/web-view-local/web-view-local',
...@@ -120,6 +119,9 @@ const pages = [ ...@@ -120,6 +119,9 @@ const pages = [
'/pages/template/swiper-list/swiper-list', '/pages/template/swiper-list/swiper-list',
'/pages/template/swiper-list2/swiper-list2', '/pages/template/swiper-list2/swiper-list2',
// '/pages/template/swiper-vertical-video/swiper-vertical-video' // '/pages/template/swiper-vertical-video/swiper-vertical-video'
// api
'/pages/API/element-draw/element-draw',
] ]
let page; let page;
......
...@@ -146,6 +146,15 @@ ...@@ -146,6 +146,15 @@
name: 'element元素', name: 'element元素',
url: 'get-element-by-id', url: 'get-element-by-id',
api: ["getElementById"] api: ["getElementById"]
},
{
name: 'element draw',
url: 'element-draw',
api: ["Element.getDrawableContext"]
},{
name: 'element截图',
url: 'element-takesnapshot',
api: ["Element.takeSnapshot"]
}, },
{ {
name: 'node节点', name: 'node节点',
......
...@@ -87,7 +87,10 @@ export default { ...@@ -87,7 +87,10 @@ export default {
*/ */
{ {
name: 'list-view', name: 'list-view',
}, },
{
name: 'sticky-header',
}
] as Page[], ] as Page[],
}, },
{ {
...@@ -217,6 +220,17 @@ export default { ...@@ -217,6 +220,17 @@ export default {
url: '/pages/component/web-view-local/web-view-local', url: '/pages/component/web-view-local/web-view-local',
}, },
] as Page[], ] as Page[],
},
{
id: 'unicloud-db',
name: 'unicloud-db',
pages: [
{
name: '联系人',
enable: true,
url: '/pages/component/unicloud-db-contacts/list'
}
] as Page[],
}, },
/* /*
{ {
......
...@@ -141,7 +141,7 @@ export default { ...@@ -141,7 +141,7 @@ export default {
{ {
id: 'scroll-sticky', id: 'scroll-sticky',
url: 'scroll-sticky', url: 'scroll-sticky',
name: '吸顶', name: 'scroll-view自定义滚动吸顶',
open: false, open: false,
pages: [] as Page[], pages: [] as Page[],
}, },
......
<template> <template>
<view style="width: 100%;height: 100%;"> <list-view style="flex: 1;" refresher-enabled=true @refresherrefresh="onRefresherrefresh"
<view class="banner" @click="bannerClick(banner)"> :refresher-triggered="refresherTriggered">
<image class="banner-img" :src="banner.cover"></image> <list-item class="banner" @click="bannerClick(banner)">
<text class="banner-title">{{ banner.title }}</text> <image class="banner-img" :src="banner.cover"></image>
</view> <text class="banner-title">{{ banner.title }}</text>
<list-view class="uni-list-content" refresher-enabled=true @refresherrefresh="onRefresherrefresh" </list-item>
:refresher-triggered="refresherTriggered" scroll-y = true> <sticky-header>
<list-item v-for="(value, index) in listData" :key="index"> <view style="width: 100%;height:44px;background-color: #f5f5f5;flex-direction: row;justify-content:center;align-items:center;">
<view class="uni-list-cell" hover-class="uni-list-cell-hover" @click="goDetail(value)"> <button style="height: 40px;font-size: 13px;" v-for="(name,index) in th_item" @click="clickTH(index)">
<view class="uni-media-list"> {{name}}
<image class="uni-media-list-logo" :src="value.cover"></image> </button>
<view class="uni-media-list-body"> </view>
<text class="uni-media-list-text-top">{{ value.title }}</text> </sticky-header>
<view class="uni-media-list-text-bottom"> <list-item v-for="(value, index) in listData" :key="index">
<text class="uni-media-list-text">{{ value.author_name }}</text> <view class="uni-list-cell" hover-class="uni-list-cell-hover" @click="goDetail(value)">
<text class="uni-media-list-text">{{ value.published_at }}</text> <view class="uni-media-list">
</view> <image class="uni-media-list-logo" :src="value.cover"></image>
</view> <view class="uni-media-list-body">
</view> <text class="uni-media-list-text-top">{{ value.title }}</text>
</view> <view class="uni-media-list-text-bottom">
</list-item> <text class="uni-media-list-text">{{ value.author_name }}</text>
</list-view> <text class="uni-media-list-text">{{ value.published_at }}</text>
</view> </view>
</view>
</view>
</view>
</list-item>
</list-view>
</template> </template>
<script> <script>
type Banner = { type Banner = {
cover: string | null, cover : string | null,
title: string | null, title : string | null,
post_id: string | null post_id : string | null
} }
type Item = { type Item = {
author_name: string, author_name : string,
cover: string, cover : string,
id: number, id : number,
post_id: string, post_id : string,
published_at: string, published_at : string,
title: string title : string
} }
export default { export default {
data() { data() {
return { return {
refresherTriggered: false, th_item: ["排序", "筛选"],
banner: {} as Banner, refresherTriggered: false,
listData: [] as Item[], banner: {} as Banner,
last_id: '', listData: [] as Item[],
pageVisible: false last_id: '',
}; pageVisible: false
}, };
onLoad() { },
this.pageVisible = true; //设这个变量是为了避免联网结束后页面已经关闭,此时还继续执行回调逻辑的问题。不是必须的 onLoad() {
this.getBanner(); this.pageVisible = true; //设这个变量是为了避免联网结束后页面已经关闭,此时还继续执行回调逻辑的问题。不是必须的
this.getList(); this.getBanner();
}, this.getList();
onUnload() { },
this.pageVisible = false; onUnload() {
}, this.pageVisible = false;
methods: { },
getBanner() { methods: {
let data = { getBanner() {
column: 'id,post_id,title,author_name,cover,published_at' //需要的字段名 let data = {
}; column: 'id,post_id,title,author_name,cover,published_at' //需要的字段名
uni.request<Banner>({ };
url: 'https://unidemo.dcloud.net.cn/api/banner/36kr', uni.request<Banner>({
data: data, url: 'https://unidemo.dcloud.net.cn/api/banner/36kr',
success: data => { data: data,
if(this.pageVisible){ success: data => {
this.refresherTriggered = false if (this.pageVisible) {
if (data.statusCode == 200) { this.refresherTriggered = false
if (data.statusCode == 200) {
const result = data.data const result = data.data
if(result != null){ if (result != null) {
this.banner = result; this.banner = result;
} }
} }
} }
}, },
fail: (e) => { fail: (e) => {
console.log('fail', e); console.log('fail', e);
} }
}); });
}, },
getList() { getList() {
let url = "https://unidemo.dcloud.net.cn/api/news?column=id,post_id,title,author_name,cover,published_at"; let url = "https://unidemo.dcloud.net.cn/api/news?column=id,post_id,title,author_name,cover,published_at";
/* if (this.last_id != "") { /* if (this.last_id != "") {
const minId = parseInt((this.last_id)) const minId = parseInt((this.last_id))
const time = new Date().getTime() + ''; const time = new Date().getTime() + '';
const pageSize = 10; const pageSize = 10;
url = url + "&minId=" + minId + "&time=" + time + "&pageSize=" + pageSize; url = url + "&minId=" + minId + "&time=" + time + "&pageSize=" + pageSize;
} */ } */
uni.request<Item[]>({ uni.request<Item[]>({
url: url, url: url,
method:"GET", method: "GET",
success: (res) => { success: (res) => {
if(this.pageVisible){ if (this.pageVisible) {
if (res.statusCode == 200) { if (res.statusCode == 200) {
console.log(res); console.log(res);
const result = res.data const result = res.data
if(result != null){ if (result != null) {
this.listData = result //因本接口没有更多分页数据,所以重新赋值。正常有分页的列表应该如下面push方式增加数组项 this.listData = result //因本接口没有更多分页数据,所以重新赋值。正常有分页的列表应该如下面push方式增加数组项
// this.listData.push(...result) // this.listData.push(...result)
// this.last_id = this.listData[0].id + ""; // this.last_id = this.listData[0].id + "";
} }
this.refresherTriggered = false; this.refresherTriggered = false;
} }
} }
}, },
fail: (res) => { fail: (res) => {
if(this.pageVisible){ if (this.pageVisible) {
console.log('fail', res); console.log('fail', res);
this.refresherTriggered = false this.refresherTriggered = false
} }
} }
}); });
}, },
goDetail(e: Item) { goDetail(e : Item) {
const detail = e; const detail = e;
const post_id = detail.post_id; const post_id = detail.post_id;
const cover = detail.cover; const cover = detail.cover;
const title = detail.title; const title = detail.title;
uni.navigateTo({ uni.navigateTo({
url: '/pages/template/list-news/detail/detail?post_id=' + post_id + "&cover=" + cover + "&title=" + title url: '/pages/template/list-news/detail/detail?post_id=' + post_id + "&cover=" + cover + "&title=" + title
}); });
}, },
bannerClick(e:Banner){ bannerClick(e : Banner) {
const detail = e; const detail = e;
const post_id = detail.post_id; const post_id = detail.post_id;
const cover = detail.cover; const cover = detail.cover;
const title = detail.title; const title = detail.title;
uni.navigateTo({ uni.navigateTo({
url: '/pages/template/list-news/detail/detail?post_id=' + post_id + "&cover=" + cover + "&title=" + title url: '/pages/template/list-news/detail/detail?post_id=' + post_id + "&cover=" + cover + "&title=" + title
}); });
}, },
onRefresherrefresh() { clickTH(index:number){
if(this.pageVisible){ uni.showModal({
this.refresherTriggered = true content: "点击表头项:" + index,
this.getBanner(); showCancel: false
this.getList(); });
} },
} onRefresherrefresh() {
} if (this.pageVisible) {
}; this.refresherTriggered = true
this.getBanner();
this.getList();
}
}
}
};
</script> </script>
<style> <style>
.banner { .banner {
height: 360rpx; height: 360rpx;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
background-color: #ccc; background-color: #ccc;
} }
.banner-img { .banner-img {
width: 100%; width: 100%;
} }
.banner-title { .banner-title {
max-height: 84rpx; max-height: 84rpx;
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
left: 30rpx; left: 30rpx;
bottom: 30rpx; bottom: 30rpx;
width: 90%; width: 90%;
font-size: 32rpx; font-size: 32rpx;
font-weight: 400; font-weight: 400;
line-height: 42rpx; line-height: 42rpx;
color: white; color: white;
} }
.uni-media-list { .uni-media-list {
padding: 22rpx 30rpx; padding: 22rpx 30rpx;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
width: 100%; width: 100%;
flex-direction: row; flex-direction: row;
} }
.uni-media-list-logo { .uni-media-list-logo {
width: 180rpx; width: 180rpx;
height: 140rpx; height: 140rpx;
} }
.uni-media-list-body { .uni-media-list-body {
flex: 1; flex: 1;
padding-left: 15rpx; padding-left: 15rpx;
justify-content: space-around; justify-content: space-around;
} }
.uni-list-content{ .uni-list-content {
background-color: #FFFFFF; background-color: #FFFFFF;
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-bottom: 1px solid #c8c7cc; border-bottom: 1px solid #c8c7cc;
flex: 1; flex: 1;
} }
.uni-media-list-text-top { .uni-media-list-text-top {
/* height: 74rpx; */ /* height: 74rpx; */
font-size: 28rpx; font-size: 28rpx;
lines:2; lines: 2;
overflow: hidden; overflow: hidden;
} }
.uni-media-list-text-bottom { .uni-media-list-text-bottom {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
} }
.uni-media-list-text { .uni-media-list-text {
color: #9D9D9F; color: #9D9D9F;
font-size: 25rpx; font-size: 25rpx;
} }
</style> </style>
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
<list-view ref="listView" class="list" :rebound="false" :scroll-y="true" :custom-nested-scroll="true" <list-view ref="listView" class="list" :rebound="false" :scroll-y="true" :custom-nested-scroll="true"
@scrolltolower="loadData(null)"> @scrolltolower="loadData(null)">
<list-item class="list-item" v-for="(item, _) in dataList" :key="item.plugin_id"> <list-item class="list-item" v-for="(item, _) in dataList" :key="item.plugin_id">
<view class="list-item-icon" v-if="item.plugin_id!=-1"> <view class="list-item-icon">
<image class="list-item-icon-image" :src="item.plugin_img_link"></image> <image class="list-item-icon-image" :src="item.plugin_img_link"></image>
</view> </view>
<view class="list-item-fill" v-if="item.plugin_id!=-1"> <view class="list-item-fill">
<view class="flex-row"> <view class="flex-row">
<text class="title">{{item.plugin_name}}</text> <text class="title">{{item.plugin_name}}</text>
</view> </view>
...@@ -22,8 +22,9 @@ ...@@ -22,8 +22,9 @@
<text class="author">{{item.author_name}}</text> <text class="author">{{item.author_name}}</text>
</view> </view>
</view> </view>
<!-- TODO 暂时这样写才能保证 loading 在 list 底部 --> </list-item>
<view v-if="item.plugin_id==-1" class="loading"> <list-item>
<view class="loading">
<text class="loading-text">{{loadingText}}</text> <text class="loading-text">{{loadingText}}</text>
</view> </view>
</list-item> </list-item>
...@@ -81,35 +82,17 @@ ...@@ -81,35 +82,17 @@
} else { } else {
return "" return ""
} }
}, }
}, },
created() { created() {
this.insertLoadingData()
if (this.preload) { if (this.preload) {
this.loadData(null) this.loadData(null)
} }
}, },
methods: { methods: {
// TODO 目前 list-item 不支持注释节点
// 暂时在数据末尾插入一条空数据用于显示 loading
insertLoadingData() {
const loadingData = {
plugin_id: -1,
plugin_img_link: '',
plugin_name: '',
plugin_intro: '',
score: 0,
tags: [],
update_date: '',
author_name: '',
} as ListItem
this.dataList.push(loadingData)
},
refreshData(loadComplete : (() => void) | null) { refreshData(loadComplete : (() => void) | null) {
this.dataList.length = 0 this.dataList.length = 0
this.$currentPage = 1 this.$currentPage = 1
this.insertLoadingData()
this.loadData(loadComplete) this.loadData(loadComplete)
}, },
loadData(loadComplete : (() => void) | null) { loadData(loadComplete : (() => void) | null) {
...@@ -131,9 +114,7 @@ ...@@ -131,9 +114,7 @@
return return
} }
// TODO this.dataList.push(...responseData.data)
this.dataList.splice(this.dataList.length - 1, 0, ...responseData.data)
// this.dataList.push(...responseData.data)
if (responseData.data.length == 0) { if (responseData.data.length == 0) {
this.isEnded = true this.isEnded = true
...@@ -254,20 +235,12 @@ ...@@ -254,20 +235,12 @@
} }
.loading { .loading {
/* position: absolute; padding: 20px;
left: 0;
top: 0;
right: 0;
bottom: 0; */
flex:1;
margin: -10px;
background-color: #f8f8f8; background-color: #f8f8f8;
margin-bottom: 1px;
justify-content: center; justify-content: center;
} }
.loading-text { .loading-text {
padding: 20px;
text-align: center; text-align: center;
} }
</style> </style>
{
"bsonType": "object",
"permission": {
"read": true,
"create": true,
"update": true,
"delete": true
},
"required": ["username", "mobile"],
"properties": {
"_id": {
"description": "存储文档 ID(用户 ID),系统自动生成"
},
"username": {
"bsonType": "string",
"title": "姓名",
"description": "姓名",
"order": 1,
"trim": "both"
},
"gender": {
"bsonType": "int",
"title": "性别",
"description": "用户性别:0 未知 1 男性 2 女性",
"order": 2,
"defaultValue": 0,
"enum": [{
"text": "未知",
"value": 0
},
{
"text": "男",
"value": 1
},
{
"text": "女",
"value": 2
}
]
},
"mobile": {
"bsonType": "string",
"title": "电话",
"order": 3,
"description": "电话",
"pattern": "^\\+?[0-9-]{3,20}$",
"trim": "both"
},
"email": {
"bsonType": "string",
"format": "email",
"title": "邮箱",
"order": 4,
"description": "邮箱地址",
"trim": "both"
},
"comment": {
"bsonType": "string",
"title": "备注",
"order": 5,
"description": "备注",
"trim": "both",
"component": {
"name": "textarea"
}
},
"create_date": {
"bsonType": "timestamp",
"description": "创建时间",
"forceDefaultValue": {
"$env": "now"
}
}
},
"version": "0.0.1"
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册