feat: worksheet发布功能开发
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"styleIsolation": "isolated",
|
||||
"usingComponents": {
|
||||
"van-popup": "@vant/weapp/popup/index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
.debug-publish-tools {
|
||||
.debug-publish-tools__fab {
|
||||
position: fixed;
|
||||
right: 24rpx;
|
||||
bottom: calc(136rpx + env(safe-area-inset-bottom));
|
||||
z-index: 40;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
padding: 20rpx 28rpx;
|
||||
border-radius: 999rpx;
|
||||
background: rgba(50, 46, 37, 0.92);
|
||||
box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
.debug-publish-tools__fab--hover {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.debug-publish-tools__fab-icon {
|
||||
font-size: 28rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.debug-publish-tools__fab-text {
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.debug-publish-tools__popup {
|
||||
width: 680rpx;
|
||||
max-height: 82vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.debug-publish-tools__content {
|
||||
max-height: 82vh;
|
||||
padding: 56rpx 32rpx 32rpx;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.debug-publish-tools__title {
|
||||
display: block;
|
||||
margin-bottom: 28rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 800;
|
||||
color: #322e25;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.debug-publish-tools__section + .debug-publish-tools__section {
|
||||
margin-top: 28rpx;
|
||||
}
|
||||
|
||||
.debug-publish-tools__section-title {
|
||||
display: block;
|
||||
margin-bottom: 18rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 700;
|
||||
color: #7c766a;
|
||||
}
|
||||
|
||||
.debug-publish-tools__meta-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.debug-publish-tools__meta-item,
|
||||
.debug-publish-tools__path-box,
|
||||
.debug-publish-tools__field {
|
||||
padding: 18rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
background: #f7f1e6;
|
||||
}
|
||||
|
||||
.debug-publish-tools__path-box {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.debug-publish-tools__meta-label,
|
||||
.debug-publish-tools__field-label {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
color: #8a8478;
|
||||
}
|
||||
|
||||
.debug-publish-tools__meta-value,
|
||||
.debug-publish-tools__path {
|
||||
display: block;
|
||||
margin-top: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #322e25;
|
||||
line-height: 1.5;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.debug-publish-tools__field + .debug-publish-tools__field {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.debug-publish-tools__input {
|
||||
width: 100%;
|
||||
margin-top: 12rpx;
|
||||
min-height: 44rpx;
|
||||
font-size: 26rpx;
|
||||
color: #322e25;
|
||||
}
|
||||
|
||||
.debug-publish-tools__chip-row {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
margin-top: 14rpx;
|
||||
}
|
||||
|
||||
.debug-publish-tools__chip-row--wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.debug-publish-tools__chip {
|
||||
min-width: 120rpx;
|
||||
padding: 16rpx 22rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #ebe3d4;
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: #605b50;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.debug-publish-tools__chip--active {
|
||||
background: #f7ce00;
|
||||
color: #453900;
|
||||
}
|
||||
|
||||
.debug-publish-tools__hint {
|
||||
display: block;
|
||||
margin-top: 10rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.6;
|
||||
color: #8a8478;
|
||||
}
|
||||
|
||||
.debug-publish-tools__actions {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
margin-top: 32rpx;
|
||||
}
|
||||
|
||||
.debug-publish-tools__btn {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
border-radius: 999rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.debug-publish-tools__btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.debug-publish-tools__btn--ghost {
|
||||
background: #f0eadf;
|
||||
color: #605b50;
|
||||
}
|
||||
|
||||
.debug-publish-tools__btn--primary {
|
||||
background: linear-gradient(135deg, #f7ee47 0%, #f0ca08 100%);
|
||||
color: #453900;
|
||||
}
|
||||
|
||||
.debug-publish-tools__processor {
|
||||
position: fixed;
|
||||
left: -9999px;
|
||||
top: -9999px;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.debug-publish-tools__processor-canvas {
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
import {
|
||||
DEBUG_PUBLISH_DEFAULT_QUALITY,
|
||||
DEBUG_PUBLISH_DEFAULT_WIDTH,
|
||||
DEBUG_PUBLISH_MAX_SIZE_KB,
|
||||
clampPublishQuality,
|
||||
clampPublishWidth,
|
||||
getCropRatios,
|
||||
normalizeTagsInput,
|
||||
type DebugCropMode,
|
||||
type DebugProcessImageParams,
|
||||
type DebugProcessImageResult,
|
||||
type DebugPublishConfirmDetail,
|
||||
type DebugPublishMeta,
|
||||
} from '../../utils/debugPublish';
|
||||
|
||||
/**
|
||||
* Debug 发布工具组件。
|
||||
*
|
||||
* 组件只负责两件事:
|
||||
* 1. 展示调试发布的 UI(悬浮按钮 + 弹窗表单)
|
||||
* 2. 用隐藏 canvas 处理预览图的裁剪与压缩
|
||||
*
|
||||
* 真正的上传云存储、调用云函数写库仍由页面层处理,
|
||||
* 这样同一套组件可以复用到多个绘制页面。
|
||||
*/
|
||||
Component({
|
||||
properties: {
|
||||
enabled: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
meta: {
|
||||
type: Object,
|
||||
value: {},
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
formTitle: '',
|
||||
formSubtitle: '',
|
||||
formTags: '',
|
||||
formStatus: 'draft',
|
||||
formCropMode: 'header-footer',
|
||||
formQuality: DEBUG_PUBLISH_DEFAULT_QUALITY,
|
||||
formWidth: DEBUG_PUBLISH_DEFAULT_WIDTH,
|
||||
maxSizeKB: DEBUG_PUBLISH_MAX_SIZE_KB,
|
||||
},
|
||||
|
||||
observers: {
|
||||
visible(visible: boolean) {
|
||||
if (visible) {
|
||||
this.syncFormState(
|
||||
(this.properties as any).meta as DebugPublishMeta | null,
|
||||
);
|
||||
}
|
||||
},
|
||||
meta(meta: DebugPublishMeta | null) {
|
||||
if ((this.properties as any).visible) {
|
||||
this.syncFormState(meta);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
ready() {
|
||||
this.initProcessorCanvas();
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
/** 打开弹窗时,用当前题型元数据重置表单。 */
|
||||
syncFormState(meta: DebugPublishMeta | null) {
|
||||
this.setData({
|
||||
formTitle: meta?.title ?? '',
|
||||
formSubtitle: meta?.subtitle ?? '',
|
||||
formTags: meta?.tags?.join(', ') ?? '',
|
||||
formStatus: meta?.status ?? 'draft',
|
||||
formCropMode: 'header-footer',
|
||||
formQuality: DEBUG_PUBLISH_DEFAULT_QUALITY,
|
||||
formWidth: DEBUG_PUBLISH_DEFAULT_WIDTH,
|
||||
});
|
||||
},
|
||||
|
||||
/** 点击悬浮发布按钮。挂载时机已由页面层控制,这里无需再二次判断 enabled。 */
|
||||
onOpen() {
|
||||
this.triggerEvent('open');
|
||||
},
|
||||
|
||||
/** 关闭发布弹窗。 */
|
||||
onClose() {
|
||||
this.triggerEvent('close');
|
||||
},
|
||||
|
||||
onTitleInput(e: WechatMiniprogram.Input) {
|
||||
this.setData({ formTitle: (e.detail.value ?? '').trim() });
|
||||
},
|
||||
|
||||
onSubtitleInput(e: WechatMiniprogram.Input) {
|
||||
this.setData({ formSubtitle: (e.detail.value ?? '').trim() });
|
||||
},
|
||||
|
||||
onTagsInput(e: WechatMiniprogram.Input) {
|
||||
this.setData({ formTags: e.detail.value ?? '' });
|
||||
},
|
||||
|
||||
onSelectStatus(e: WechatMiniprogram.TouchEvent) {
|
||||
const value = e.currentTarget.dataset.value as string;
|
||||
if (!value) return;
|
||||
this.setData({ formStatus: value });
|
||||
},
|
||||
|
||||
onSelectCropMode(e: WechatMiniprogram.TouchEvent) {
|
||||
const value = e.currentTarget.dataset.value as DebugCropMode;
|
||||
if (!value) return;
|
||||
this.setData({ formCropMode: value });
|
||||
},
|
||||
|
||||
onQualityChange(e: WechatMiniprogram.CustomEvent) {
|
||||
this.setData({
|
||||
formQuality: clampPublishQuality(Number(e.detail.value)),
|
||||
});
|
||||
},
|
||||
|
||||
onWidthChange(e: WechatMiniprogram.CustomEvent) {
|
||||
this.setData({
|
||||
formWidth: clampPublishWidth(Number(e.detail.value)),
|
||||
});
|
||||
},
|
||||
|
||||
/** 校验弹窗输入,并把结果回传给页面层。 */
|
||||
onConfirm() {
|
||||
const meta = (this.properties as any)
|
||||
.meta as DebugPublishMeta | null;
|
||||
if (!meta) {
|
||||
wx.showToast({
|
||||
title: '缺少发布元数据',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const title = this.data.formTitle.trim();
|
||||
const subtitle = this.data.formSubtitle.trim();
|
||||
if (!title || !subtitle) {
|
||||
wx.showToast({
|
||||
title: '标题和副标题不能为空',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const detail: DebugPublishConfirmDetail = {
|
||||
meta: {
|
||||
title,
|
||||
subtitle,
|
||||
tags: normalizeTagsInput(this.data.formTags),
|
||||
status: this.data.formStatus as DebugPublishMeta['status'],
|
||||
},
|
||||
settings: {
|
||||
cropMode: this.data.formCropMode as DebugCropMode,
|
||||
quality: clampPublishQuality(this.data.formQuality),
|
||||
width: clampPublishWidth(this.data.formWidth),
|
||||
maxSizeKB: this.data.maxSizeKB,
|
||||
},
|
||||
};
|
||||
|
||||
this.triggerEvent('confirm', detail);
|
||||
},
|
||||
|
||||
/** 初始化隐藏处理 canvas,后续所有裁剪压缩都在这里完成。 */
|
||||
initProcessorCanvas() {
|
||||
if ((this as any)._processorCanvasReadyPromise) return;
|
||||
|
||||
(this as any)._processorCanvasReadyPromise = new Promise<void>(
|
||||
(resolve, reject) => {
|
||||
this.createSelectorQuery()
|
||||
.select('#processorCanvas')
|
||||
.fields({ node: true, size: true })
|
||||
.exec((res) => {
|
||||
if (!res[0] || !res[0].node) {
|
||||
reject(new Error('处理画布初始化失败'));
|
||||
return;
|
||||
}
|
||||
|
||||
(this as any)._processorCanvas = res[0].node;
|
||||
(this as any)._processorCtx = (
|
||||
this as any
|
||||
)._processorCanvas.getContext('2d');
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
/** 确保隐藏 canvas 已经 ready。 */
|
||||
async ensureProcessorCanvasReady() {
|
||||
if (!(this as any)._processorCanvasReadyPromise) {
|
||||
this.initProcessorCanvas();
|
||||
}
|
||||
await (this as any)._processorCanvasReadyPromise;
|
||||
},
|
||||
|
||||
/** 用当前 canvas 上下文加载临时图片文件。 */
|
||||
loadImage(
|
||||
canvas: WechatMiniprogram.Canvas,
|
||||
src: string,
|
||||
): Promise<WechatMiniprogram.Image> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const image = canvas.createImage();
|
||||
image.onload = () => resolve(image);
|
||||
image.onerror = reject;
|
||||
image.src = src;
|
||||
});
|
||||
},
|
||||
|
||||
/** 将处理后的 canvas 导出成 jpg 临时文件。 */
|
||||
exportCanvasToTempFile(
|
||||
canvas: WechatMiniprogram.Canvas,
|
||||
width: number,
|
||||
height: number,
|
||||
quality: number,
|
||||
): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.canvasToTempFilePath({
|
||||
canvas,
|
||||
fileType: 'jpg',
|
||||
quality,
|
||||
destWidth: width,
|
||||
destHeight: height,
|
||||
success: (res) => resolve(res.tempFilePath),
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 读取导出文件大小,用于控制最大体积。
|
||||
* 开发者工具中 canvasToTempFilePath 可能返回 HTTP URL,
|
||||
* wx.getFileSystemManager().getFileInfo() 不支持 HTTP 路径,
|
||||
* 此时返回 -1 表示无法获取大小,调用方应跳过体积检测。
|
||||
*/
|
||||
getFileSize(filePath: string): Promise<number> {
|
||||
return new Promise((resolve) => {
|
||||
wx.getFileSystemManager().getFileInfo({
|
||||
filePath,
|
||||
success: (res) => resolve(res.size),
|
||||
fail: () => resolve(-1),
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 裁剪并压缩入口图。
|
||||
*
|
||||
* 流程:
|
||||
* 1. 加载 preview-card 导出的完整 A4 图片
|
||||
* 2. 按裁剪模式裁掉页眉 / 页脚
|
||||
* 3. 按目标宽度重绘到隐藏 canvas
|
||||
* 4. 若体积超出阈值,则逐步降低 jpg quality
|
||||
*/
|
||||
async processImage(
|
||||
params: DebugProcessImageParams,
|
||||
): Promise<DebugProcessImageResult> {
|
||||
await this.ensureProcessorCanvasReady();
|
||||
|
||||
const canvas = (this as any)
|
||||
._processorCanvas as WechatMiniprogram.Canvas;
|
||||
const ctx = (this as any)._processorCtx as RenderingContext;
|
||||
if (!canvas || !ctx) {
|
||||
throw new Error('处理画布不可用');
|
||||
}
|
||||
|
||||
const image = await this.loadImage(canvas, params.sourcePath);
|
||||
const { topRatio, bottomRatio } = getCropRatios(
|
||||
params.settings.cropMode,
|
||||
);
|
||||
const sourceWidth = image.width;
|
||||
const sourceHeight = image.height;
|
||||
const cropTop = Math.round(sourceHeight * topRatio);
|
||||
const cropBottom = Math.round(sourceHeight * bottomRatio);
|
||||
const extractHeight = sourceHeight - cropTop - cropBottom;
|
||||
|
||||
if (extractHeight <= 0) {
|
||||
throw new Error('裁剪区域无效');
|
||||
}
|
||||
|
||||
const targetWidth = clampPublishWidth(params.settings.width);
|
||||
const targetHeight = Math.round(
|
||||
(extractHeight * targetWidth) / sourceWidth,
|
||||
);
|
||||
|
||||
canvas.width = targetWidth;
|
||||
canvas.height = targetHeight;
|
||||
ctx.clearRect(0, 0, targetWidth, targetHeight);
|
||||
ctx.drawImage(
|
||||
image,
|
||||
0,
|
||||
cropTop,
|
||||
sourceWidth,
|
||||
extractHeight,
|
||||
0,
|
||||
0,
|
||||
targetWidth,
|
||||
targetHeight,
|
||||
);
|
||||
|
||||
let currentQuality =
|
||||
clampPublishQuality(params.settings.quality) / 100;
|
||||
let outputPath = '';
|
||||
let outputSize = 0;
|
||||
|
||||
while (currentQuality >= 0.35) {
|
||||
outputPath = await this.exportCanvasToTempFile(
|
||||
canvas,
|
||||
targetWidth,
|
||||
targetHeight,
|
||||
currentQuality,
|
||||
);
|
||||
outputSize = await this.getFileSize(outputPath);
|
||||
|
||||
// -1 表示无法获取大小(开发者工具 HTTP 路径),直接跳过体积循环
|
||||
if (
|
||||
outputSize < 0 ||
|
||||
outputSize <= params.settings.maxSizeKB * 1024
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
currentQuality =
|
||||
Math.round((currentQuality - 0.05) * 100) / 100;
|
||||
}
|
||||
|
||||
return {
|
||||
tempFilePath: outputPath,
|
||||
size: outputSize,
|
||||
width: targetWidth,
|
||||
height: targetHeight,
|
||||
quality: Math.round(currentQuality * 100),
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,183 @@
|
||||
<view class="debug-publish-tools">
|
||||
<view
|
||||
class="debug-publish-tools__fab"
|
||||
hover-class="debug-publish-tools__fab--hover"
|
||||
hover-start-time="0"
|
||||
hover-stay-time="70"
|
||||
catchtap="onOpen">
|
||||
<text class="debug-publish-tools__fab-icon">📤</text>
|
||||
<text class="debug-publish-tools__fab-text">发布到云端</text>
|
||||
</view>
|
||||
|
||||
<van-popup
|
||||
show="{{visible}}"
|
||||
position="center"
|
||||
round
|
||||
closeable="{{!loading}}"
|
||||
close-on-click-overlay="{{!loading}}"
|
||||
bind:close="onClose"
|
||||
custom-class="debug-publish-tools__popup">
|
||||
<view class="debug-publish-tools__content">
|
||||
<text class="debug-publish-tools__title">Debug 发布</text>
|
||||
|
||||
<view wx:if="{{meta}}" class="debug-publish-tools__section">
|
||||
<text class="debug-publish-tools__section-title">基础信息</text>
|
||||
<view class="debug-publish-tools__meta-grid">
|
||||
<view class="debug-publish-tools__meta-item">
|
||||
<text class="debug-publish-tools__meta-label">ID</text>
|
||||
<text class="debug-publish-tools__meta-value">{{meta.id}}</text>
|
||||
</view>
|
||||
<view class="debug-publish-tools__meta-item">
|
||||
<text class="debug-publish-tools__meta-label">分类</text>
|
||||
<text class="debug-publish-tools__meta-value">{{meta.category}}</text>
|
||||
</view>
|
||||
<view class="debug-publish-tools__meta-item">
|
||||
<text class="debug-publish-tools__meta-label">年龄</text>
|
||||
<text class="debug-publish-tools__meta-value">
|
||||
{{meta.ageMin}}-{{meta.ageMax}} 岁
|
||||
</text>
|
||||
</view>
|
||||
<view class="debug-publish-tools__meta-item">
|
||||
<text class="debug-publish-tools__meta-label">难度</text>
|
||||
<text class="debug-publish-tools__meta-value">{{meta.difficulty}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="debug-publish-tools__path-box">
|
||||
<text class="debug-publish-tools__meta-label">路径</text>
|
||||
<text class="debug-publish-tools__path">{{meta.path}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="debug-publish-tools__section">
|
||||
<text class="debug-publish-tools__section-title">资料信息</text>
|
||||
<view class="debug-publish-tools__field">
|
||||
<text class="debug-publish-tools__field-label">标题</text>
|
||||
<input
|
||||
class="debug-publish-tools__input"
|
||||
value="{{formTitle}}"
|
||||
maxlength="20"
|
||||
bindinput="onTitleInput" />
|
||||
</view>
|
||||
<view class="debug-publish-tools__field">
|
||||
<text class="debug-publish-tools__field-label">副标题</text>
|
||||
<input
|
||||
class="debug-publish-tools__input"
|
||||
value="{{formSubtitle}}"
|
||||
maxlength="40"
|
||||
bindinput="onSubtitleInput" />
|
||||
</view>
|
||||
<view class="debug-publish-tools__field">
|
||||
<text class="debug-publish-tools__field-label">标签</text>
|
||||
<input
|
||||
class="debug-publish-tools__input"
|
||||
value="{{formTags}}"
|
||||
placeholder="多个标签用逗号分隔"
|
||||
maxlength="80"
|
||||
bindinput="onTagsInput" />
|
||||
</view>
|
||||
<view class="debug-publish-tools__field">
|
||||
<text class="debug-publish-tools__field-label">状态</text>
|
||||
<view class="debug-publish-tools__chip-row">
|
||||
<view
|
||||
class="debug-publish-tools__chip {{formStatus === 'draft' ? 'debug-publish-tools__chip--active' : ''}}"
|
||||
data-value="draft"
|
||||
bindtap="onSelectStatus">
|
||||
draft
|
||||
</view>
|
||||
<view
|
||||
class="debug-publish-tools__chip {{formStatus === 'active' ? 'debug-publish-tools__chip--active' : ''}}"
|
||||
data-value="active"
|
||||
bindtap="onSelectStatus">
|
||||
active
|
||||
</view>
|
||||
<view
|
||||
class="debug-publish-tools__chip {{formStatus === 'hidden' ? 'debug-publish-tools__chip--active' : ''}}"
|
||||
data-value="hidden"
|
||||
bindtap="onSelectStatus">
|
||||
hidden
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="debug-publish-tools__section">
|
||||
<text class="debug-publish-tools__section-title">图片处理</text>
|
||||
<view class="debug-publish-tools__field">
|
||||
<text class="debug-publish-tools__field-label">裁剪模式</text>
|
||||
<view class="debug-publish-tools__chip-row debug-publish-tools__chip-row--wrap">
|
||||
<view
|
||||
class="debug-publish-tools__chip {{formCropMode === 'header-footer' ? 'debug-publish-tools__chip--active' : ''}}"
|
||||
data-value="header-footer"
|
||||
bindtap="onSelectCropMode">
|
||||
裁剪头尾
|
||||
</view>
|
||||
<view
|
||||
class="debug-publish-tools__chip {{formCropMode === 'header-only' ? 'debug-publish-tools__chip--active' : ''}}"
|
||||
data-value="header-only"
|
||||
bindtap="onSelectCropMode">
|
||||
仅裁头部
|
||||
</view>
|
||||
<view
|
||||
class="debug-publish-tools__chip {{formCropMode === 'none' ? 'debug-publish-tools__chip--active' : ''}}"
|
||||
data-value="none"
|
||||
bindtap="onSelectCropMode">
|
||||
不裁剪
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="debug-publish-tools__field">
|
||||
<text class="debug-publish-tools__field-label">
|
||||
压缩质量 {{formQuality}}
|
||||
</text>
|
||||
<slider
|
||||
min="40"
|
||||
max="95"
|
||||
step="5"
|
||||
value="{{formQuality}}"
|
||||
activeColor="#f7ce00"
|
||||
backgroundColor="#ece4d2"
|
||||
bindchange="onQualityChange" />
|
||||
</view>
|
||||
<view class="debug-publish-tools__field">
|
||||
<text class="debug-publish-tools__field-label">
|
||||
输出宽度 {{formWidth}}px
|
||||
</text>
|
||||
<slider
|
||||
min="400"
|
||||
max="1000"
|
||||
step="20"
|
||||
value="{{formWidth}}"
|
||||
activeColor="#f7ce00"
|
||||
backgroundColor="#ece4d2"
|
||||
bindchange="onWidthChange" />
|
||||
</view>
|
||||
<text class="debug-publish-tools__hint">
|
||||
默认按文档规则裁掉页眉和页脚,并尽量压缩到 {{maxSizeKB}}KB 内。
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="debug-publish-tools__actions">
|
||||
<button
|
||||
class="debug-publish-tools__btn debug-publish-tools__btn--ghost"
|
||||
disabled="{{loading}}"
|
||||
bindtap="onClose">
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
class="debug-publish-tools__btn debug-publish-tools__btn--primary"
|
||||
loading="{{loading}}"
|
||||
disabled="{{loading}}"
|
||||
bindtap="onConfirm">
|
||||
确认发布
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</van-popup>
|
||||
|
||||
<view class="debug-publish-tools__processor">
|
||||
<canvas
|
||||
id="processorCanvas"
|
||||
type="2d"
|
||||
class="debug-publish-tools__processor-canvas" />
|
||||
</view>
|
||||
</view>
|
||||
Reference in New Issue
Block a user