extrafile gallery 支持小程序文件上传

This commit is contained in:
Wang Kejun 2023-02-09 20:00:42 +08:00
parent 781cfae13a
commit 36913ec5eb
28 changed files with 606 additions and 126 deletions

View File

@ -47,6 +47,7 @@ export declare function sendCaptcha<ED extends EntityDict, Cxt extends BackendRu
export declare function switchTo<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>>({ userId }: {
userId: string;
}, context: Cxt): Promise<void>;
export declare function getWechatMpUserPhoneNumber<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>>({ code }: {
export declare function getWechatMpUserPhoneNumber<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>>({ code, env }: {
code: string;
env: WechatMpEnv;
}, context: Cxt): Promise<string>;

View File

@ -1347,9 +1347,9 @@ function switchTo(_a, context) {
}
exports.switchTo = switchTo;
function getWechatMpUserPhoneNumber(_a, context) {
var code = _a.code;
var code = _a.code, env = _a.env;
return tslib_1.__awaiter(this, void 0, void 0, function () {
var application, _b, type, config, systemId, config2, appId, appSecret, wechatInstance, result, purePhoneNumber;
var application, _b, type, config, systemId, config2, appId, appSecret, wechatInstance, result, phoneNumber;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
@ -1362,9 +1362,9 @@ function getWechatMpUserPhoneNumber(_a, context) {
return [4 /*yield*/, wechatInstance.getUserPhoneNumber(code)];
case 1:
result = _c.sent();
purePhoneNumber = result === null || result === void 0 ? void 0 : result.purePhoneNumber;
//todo 需要干什么
return [2 /*return*/, '授权成功'];
phoneNumber = result === null || result === void 0 ? void 0 : result.phoneNumber;
return [4 /*yield*/, setupMobile(phoneNumber, env, context)];
case 2: return [2 /*return*/, _c.sent()];
}
});
});

View File

@ -20,6 +20,7 @@ exports.default = OakComponent({
type: 1,
entity: 1,
entityId: 1,
fileType: 1,
},
formData: function (_a) {
var _this = this;
@ -38,7 +39,6 @@ exports.default = OakComponent({
};
},
data: {
selected: -1,
// 根据 size 不同,计算的图片显示大小不同
itemSizePercentage: '',
},
@ -57,8 +57,8 @@ exports.default = OakComponent({
Object.assign(filter1, { tag2: tag2 });
}
return filter1;
}
}
},
},
],
properties: {
removeLater: Boolean,
@ -70,6 +70,15 @@ exports.default = OakComponent({
type: Number,
value: 20,
},
extension: {
//小程序独有 chooseMessageFile 根据文件拓展名过滤,仅 type==file 时有效。每一项都不能是空字符串。默认不过滤。
type: Array,
},
fileType: {
//小程序独有 chooseMessageFile 文件type
type: String,
value: 'all',
},
selectCount: {
//小程序独有 文件一次选择几个
type: Number,
@ -84,6 +93,18 @@ exports.default = OakComponent({
type: Array,
value: ['image'],
},
// 图片显示模式
mode: {
//小程序独有
type: String,
value: 'aspectFit',
},
// 每行可显示的个数
size: {
// 小程序独有
type: Number,
value: 3,
},
showUploadList: {
// web独有 是否展示文件列表, 可设为一个对象
type: Boolean,
@ -94,23 +115,11 @@ exports.default = OakComponent({
type: String,
value: 'image/*',
},
// 图片显示模式
mode: {
//小程序独有
type: String,
value: 'aspectFit',
},
// 图片是否可预览
preview: {
type: Boolean,
value: true,
},
// 每行可显示的个数
size: {
// 小程序独有
type: Number,
value: 3,
},
// 图片是否可删除
disableDelete: {
type: Boolean,
@ -122,6 +131,10 @@ exports.default = OakComponent({
tag2: String,
entity: String,
entityId: String,
theme: {
type: String,
value: 'image',
},
},
methods: {
/**
@ -156,7 +169,7 @@ exports.default = OakComponent({
var windowWidth = wx.getSystemInfoSync().windowWidth;
return (750 / windowWidth) * px;
},
onPickByMp: function () {
chooseMediaByMp: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, selectCount, mediaType, sourceType, _b, errMsg, tempFiles, err_1;
var _this = this;
@ -183,16 +196,21 @@ exports.default = OakComponent({
case 3: return [4 /*yield*/, Promise.all(tempFiles.map(function (tempExtraFile) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var tempFilePath, thumbTempFilePath, fileType, size, filePath, fileFullName;
return tslib_1.__generator(this, function (_a) {
tempFilePath = tempExtraFile.tempFilePath, thumbTempFilePath = tempExtraFile.thumbTempFilePath, fileType = tempExtraFile.fileType, size = tempExtraFile.size;
filePath = tempFilePath || thumbTempFilePath;
fileFullName = filePath.match(/[^/]+(?!.*\/)/g)[0];
this.pushExtraFile({
name: fileFullName,
fileType: fileType,
size: size,
extra1: filePath,
});
return [2 /*return*/];
switch (_a.label) {
case 0:
tempFilePath = tempExtraFile.tempFilePath, thumbTempFilePath = tempExtraFile.thumbTempFilePath, fileType = tempExtraFile.fileType, size = tempExtraFile.size;
filePath = tempFilePath || thumbTempFilePath;
fileFullName = filePath.match(/[^/]+(?!.*\/)/g)[0];
return [4 /*yield*/, this.pushExtraFile({
name: fileFullName,
fileType: fileType,
size: size,
extra1: filePath,
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); }))];
case 4:
@ -214,20 +232,92 @@ exports.default = OakComponent({
});
});
},
chooseFileByMp: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, selectCount, extension, fileType, _b, errMsg, tempFiles, err_2;
var _this = this;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
_a = this.props, selectCount = _a.selectCount, extension = _a.extension, fileType = _a.fileType;
_c.label = 1;
case 1:
_c.trys.push([1, 6, , 7]);
return [4 /*yield*/, wx.chooseMessageFile(tslib_1.__assign({ count: selectCount, type: 'all' }, (fileType === 'file' ? { extension: extension } : {})))];
case 2:
_b = _c.sent(), errMsg = _b.errMsg, tempFiles = _b.tempFiles;
if (!(errMsg !== 'chooseMessageFile:ok')) return [3 /*break*/, 3];
this.triggerEvent('error', {
level: 'warning',
msg: errMsg,
});
return [3 /*break*/, 5];
case 3: return [4 /*yield*/, Promise.all(tempFiles.map(function (tempExtraFile) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var path, type, size, name;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
path = tempExtraFile.path, type = tempExtraFile.type, size = tempExtraFile.size, name = tempExtraFile.name;
// const fileType = name.substring(
// name.lastIndexOf('.') + 1
// );
return [4 /*yield*/, this.pushExtraFile({
name: name,
fileType: type,
size: size,
extra1: path,
})];
case 1:
// const fileType = name.substring(
// name.lastIndexOf('.') + 1
// );
_a.sent();
return [2 /*return*/];
}
});
}); }))];
case 4:
_c.sent();
_c.label = 5;
case 5: return [3 /*break*/, 7];
case 6:
err_2 = _c.sent();
console.error(err_2);
if (err_2.errMsg !== 'chooseMessageFile:fail cancel') {
this.triggerEvent('error', {
level: 'error',
msg: err_2.errMsg,
});
}
return [3 /*break*/, 7];
case 7: return [2 /*return*/];
}
});
});
},
onPickByMp: function () {
var theme = this.props.theme;
if (['image', 'image-flow'].includes(theme)) {
this.chooseMediaByMp();
}
else {
this.chooseFileByMp();
}
},
onPickByWeb: function (uploadFiles, callback) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _this = this;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Promise.all(uploadFiles.map(function (uploadFile) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var name, fileType, size, raw, originFileObj;
var name, type, size, originFileObj;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
name = uploadFile.name, fileType = uploadFile.type, size = uploadFile.size, raw = uploadFile.raw, originFileObj = uploadFile.originFileObj;
name = uploadFile.name, type = uploadFile.type, size = uploadFile.size, originFileObj = uploadFile.originFileObj;
return [4 /*yield*/, this.pushExtraFile({
name: name,
fileType: fileType,
fileType: type,
size: size,
extra1: originFileObj,
}, callback)];
@ -431,6 +521,87 @@ exports.default = OakComponent({
});
});
},
onDownloadByMp: function (event) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var value, fileUrl, name;
return tslib_1.__generator(this, function (_a) {
value = event.currentTarget.dataset.value;
fileUrl = this.features.extraFile.getUrl(value);
name = value.filename + '.' + value.extension;
wx.showLoading({
title: '下载请求中,请耐心等待..',
});
wx.downloadFile({
url: fileUrl,
success: function (res) {
var filePath = res.tempFilePath || res.filePath;
wx.hideLoading();
var fs = wx.getFileSystemManager();
var writeFilePath = "".concat(wx.env.USER_DATA_PATH, "/").concat(name);
var res2 = fs.saveFileSync(filePath, writeFilePath);
},
fail: function (res) {
console.log(res);
},
complete: function (res) { },
});
return [2 /*return*/];
});
});
},
onOpenByMp: function (event) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var value, fileUrl, extension, extensions;
return tslib_1.__generator(this, function (_a) {
value = event.currentTarget.dataset.value;
fileUrl = this.features.extraFile.getUrl(value);
extension = value.extension.toLowerCase();
extensions = [
'doc',
'docx',
'xls',
'xlsx',
'ppt',
'pptx',
'pdf',
];
if (!extensions.includes(extension)) {
this.setMessage({
type: 'error',
content: "\u76EE\u524D\u4EC5\u652F\u6301\u6253\u5F00".concat(extensions.join(','), "\u7C7B\u578B\u7684\u6587\u4EF6"),
});
return [2 /*return*/];
}
wx.showLoading({
title: '下载请求中,请耐心等待..',
});
wx.downloadFile({
url: fileUrl,
success: function (res) {
var filePath = res.tempFilePath || res.filePath;
wx.hideLoading();
wx.openDocument({
//打开文件
filePath: filePath,
fileType: extension,
showMenu: true,
success: function () {
console.log("\u6253\u5F00\u6587\u4EF6\u6210\u529F");
},
fail: function (err) {
console.log(err);
},
});
},
fail: function (res) {
console.log(res);
},
complete: function (res) { },
});
return [2 /*return*/];
});
});
},
},
observers: {
maxNumber: function () {

View File

@ -2,6 +2,7 @@
"component": true,
"usingComponents": {
"l-icon": "../../../miniprogram_npm/lin-ui/icon/index",
"l-button": "../../../miniprogram_npm/lin-ui/button/index",
"oak-display": "../display/index"
}
}

View File

@ -1,7 +1,7 @@
import { UploadFile } from 'antd';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../general-app-domain';
declare type Theme = 'file' | 'image' | 'file-flow' | 'image-flow' | 'custom';
declare type Theme = 'file' | 'image' | 'image-flow' | 'custom';
export default function render(props: WebComponentProps<EntityDict, 'extraFile', true, {
accept?: string;
maxNumber?: number;

View File

@ -13,7 +13,6 @@ function getListType(theme) {
var themeMap = {
file: 'text',
image: 'picture-card',
'file-flow': 'text',
'image-flow': 'picture',
custom: 'text',
};
@ -36,12 +35,14 @@ function render(props) {
}
}, [files]);
var extraFileToUploadFile = function (extraFile) {
var filename = extraFile.filename +
(extraFile.extension ? ".".concat(extraFile.extension) : '');
return {
id: extraFile.id,
url: features.extraFile.getUrl(extraFile),
thumbUrl: features.extraFile.getUrl(extraFile),
name: extraFile.filename + (extraFile.extension || ''),
fileName: extraFile.filename + (extraFile.extension || ''),
name: filename,
fileName: filename,
size: extraFile.size,
type: extraFile.fileType,
uid: extraFile.id, //upload 组件需要uid来维护fileList

View File

@ -2,7 +2,7 @@ import { String, Int, Text } from 'oak-domain/lib/types/DataType';
import { EntityShape } from 'oak-domain/lib/types/Entity';
export interface Schema extends EntityShape {
origin: 'qiniu' | 'unknown';
type: 'image' | 'video' | 'audio' | 'file' | 'pdf';
type: 'image' | 'video' | 'audio' | 'file';
bucket: String<16>;
objectId: String<64>;
tag1: String<16>;

View File

@ -30,7 +30,6 @@ var locale = {
video: '视频',
audio: '音频',
file: '文件',
pdf: 'pdf',
},
},
},

View File

@ -16,5 +16,6 @@ export declare class ExtraFile<ED extends EntityDict, Cxt extends BackendRuntime
bucket: string;
}>;
getUrl(extraFile?: EntityDict['extraFile']['OpSchema'] | null, style?: string): string;
getFileName(extraFile: EntityDict['extraFile']['OpSchema']): string;
formatBytes(size: number): string;
}

View File

@ -69,6 +69,11 @@ var ExtraFile = /** @class */ (function (_super) {
var url = (0, extraFile_1.composeFileUrl)(extraFile, config, style);
return url;
};
ExtraFile.prototype.getFileName = function (extraFile) {
var name = extraFile.filename +
(extraFile.extension ? ".".concat(extraFile.extension) : '');
return name;
};
ExtraFile.prototype.formatBytes = function (size) {
return (0, extraFile_1.bytesToSize)(size);
};

View File

@ -30,5 +30,5 @@ export declare class Token<ED extends EntityDict, Cxt extends BackendRuntimeCont
sendCaptcha(mobile: string): Promise<string>;
switchTo(userId: string): Promise<void>;
refreshWechatPublicUserInfo(): Promise<void>;
getWechatMpUserPhoneNumber(): Promise<void>;
getWechatMpUserPhoneNumber(code: string): Promise<void>;
}

View File

@ -251,12 +251,19 @@ var Token = /** @class */ (function (_super) {
});
});
};
Token.prototype.getWechatMpUserPhoneNumber = function () {
Token.prototype.getWechatMpUserPhoneNumber = function (code) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var env;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.cache.exec('getWechatMpUserPhoneNumber', {})];
case 0: return [4 /*yield*/, (0, env_1.getEnv)()];
case 1:
env = _a.sent();
return [4 /*yield*/, this.cache.exec('getWechatMpUserPhoneNumber', {
code: code,
env: env,
})];
case 2:
_a.sent();
this.publish();
return [2 /*return*/];

View File

@ -1118,7 +1118,7 @@ export async function switchTo<ED extends EntityDict, Cxt extends BackendRuntime
export async function getWechatMpUserPhoneNumber<
ED extends EntityDict,
Cxt extends BackendRuntimeContext<ED>
>({ code }: { code: string }, context: Cxt) {
>({ code, env }: { code: string; env: WechatMpEnv }, context: Cxt) {
const application = context.getApplication();
const { type, config, systemId } = application!;
assert(type === 'wechatMp' && config!.type === 'wechatMp');
@ -1130,10 +1130,7 @@ export async function getWechatMpUserPhoneNumber<
'wechatMp'
) as WechatMpInstance;
const result = await wechatInstance.getUserPhoneNumber(code);
//获取 没区号的手机号码
const purePhoneNumber = result?.purePhoneNumber;
//todo 需要干什么
return '授权成功'
//获取 绑定的手机号码
const phoneNumber = result?.phoneNumber;
return await setupMobile<ED, Cxt>(phoneNumber, env, context);
}

View File

@ -2,6 +2,7 @@
"component": true,
"usingComponents": {
"l-icon": "../../../miniprogram_npm/lin-ui/icon/index",
"l-button": "../../../miniprogram_npm/lin-ui/button/index",
"oak-display": "../display/index"
}
}

View File

@ -107,4 +107,46 @@ each(range(2, 10), {
.file-list__item-slot-wrapper:empty+.file-list__image--add {
visibility: visible;
}
.file-list-flow__container {
position: relative;
display: flex;
flex-direction: column;
}
.file-list-flow__item {
display: flex;
flex-direction: row;
align-items: center;
margin: 10rpx 10rpx 10rpx 0;
}
.file-list-flow__item--name {
display: flex;
flex-direction: row;
fleX: 1;
font-size: 28rpx;
}
.file-list-flow__item--btns {
display: flex;
flex-direction: row;
}
.file-list-flow__download {
width: 48rpx;
height: 48rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.file-list-flow__remove {
width: 48rpx;
height: 48rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

View File

@ -19,6 +19,7 @@ export default OakComponent({
type: 1,
entity: 1,
entityId: 1,
fileType: 1,
},
formData({ data: originalFiles, features }) {
let files = (
@ -38,7 +39,6 @@ export default OakComponent({
};
},
data: {
selected: -1,
// 根据 size 不同,计算的图片显示大小不同
itemSizePercentage: '',
},
@ -57,9 +57,8 @@ export default OakComponent({
Object.assign(filter1, { tag2 });
}
return filter1;
}
}
},
},
],
properties: {
removeLater: Boolean,
@ -71,6 +70,15 @@ export default OakComponent({
type: Number,
value: 20,
},
extension: {
//小程序独有 chooseMessageFile 根据文件拓展名过滤,仅 type==file 时有效。每一项都不能是空字符串。默认不过滤。
type: Array,
},
fileType: {
//小程序独有 chooseMessageFile 文件type
type: String,
value: 'all',
},
selectCount: {
//小程序独有 文件一次选择几个
type: Number,
@ -85,6 +93,18 @@ export default OakComponent({
type: Array,
value: ['image'],
},
// 图片显示模式
mode: {
//小程序独有
type: String,
value: 'aspectFit',
},
// 每行可显示的个数
size: {
// 小程序独有
type: Number,
value: 3,
},
showUploadList: {
// web独有 是否展示文件列表, 可设为一个对象
type: Boolean,
@ -95,23 +115,11 @@ export default OakComponent({
type: String,
value: 'image/*',
},
// 图片显示模式
mode: {
//小程序独有
type: String,
value: 'aspectFit',
},
// 图片是否可预览
preview: {
type: Boolean,
value: true,
},
// 每行可显示的个数
size: {
// 小程序独有
type: Number,
value: 3,
},
// 图片是否可删除
disableDelete: {
type: Boolean,
@ -123,6 +131,10 @@ export default OakComponent({
tag2: String,
entity: String,
entityId: String,
theme: {
type: String,
value: 'image',
},
},
methods: {
@ -151,7 +163,7 @@ export default OakComponent({
const windowWidth = wx.getSystemInfoSync().windowWidth;
return (750 / windowWidth) * px;
},
async onPickByMp() {
async chooseMediaByMp() {
const { selectCount, mediaType, sourceType } = this.props;
try {
const { errMsg, tempFiles } = await wx.chooseMedia({
@ -176,7 +188,7 @@ export default OakComponent({
const filePath = tempFilePath || thumbTempFilePath;
const fileFullName =
filePath.match(/[^/]+(?!.*\/)/g)![0];
this.pushExtraFile({
await this.pushExtraFile({
name: fileFullName,
fileType,
size,
@ -195,23 +207,64 @@ export default OakComponent({
}
}
},
async chooseFileByMp() {
const { selectCount, extension, fileType } = this.props;
try {
const { errMsg, tempFiles } = await wx.chooseMessageFile({
count: selectCount,
type: 'all',
...(fileType === 'file' ? { extension } : {}),
});
if (errMsg !== 'chooseMessageFile:ok') {
this.triggerEvent('error', {
level: 'warning',
msg: errMsg,
});
} else {
await Promise.all(
tempFiles.map(async (tempExtraFile) => {
const { path, type, size, name } = tempExtraFile;
// const fileType = name.substring(
// name.lastIndexOf('.') + 1
// );
await this.pushExtraFile({
name,
fileType: type,
size,
extra1: path,
});
})
);
}
} catch (err: any) {
console.error(err);
if (err.errMsg !== 'chooseMessageFile:fail cancel') {
this.triggerEvent('error', {
level: 'error',
msg: err.errMsg,
});
}
}
},
onPickByMp() {
const { theme } = this.props;
if (['image', 'image-flow'].includes(theme)) {
this.chooseMediaByMp();
} else {
this.chooseFileByMp();
}
},
async onPickByWeb(
uploadFiles: any[],
callback?: (file: any, status: string) => void
) {
await Promise.all(
uploadFiles.map(async (uploadFile) => {
const {
name,
type: fileType,
size,
raw,
originFileObj,
} = uploadFile;
const { name, type, size, originFileObj } = uploadFile;
await this.pushExtraFile(
{
name,
fileType,
fileType: type,
size,
extra1: originFileObj,
},
@ -360,6 +413,76 @@ export default OakComponent({
});
}
},
async onDownloadByMp(event: WechatMiniprogram.Touch) {
const { value } = event.currentTarget.dataset;
const fileUrl = this.features.extraFile.getUrl(value);
const name = this.features.extraFile.getFileName(value);
wx.showLoading({
title: '下载请求中,请耐心等待..',
});
wx.downloadFile({
url: fileUrl,
success: function (res) {
const filePath = res.tempFilePath || res.filePath;
wx.hideLoading();
const fs = wx.getFileSystemManager();
const writeFilePath = `${wx.env.USER_DATA_PATH}/${name}`;
const res2 = fs.saveFileSync(filePath, writeFilePath);
},
fail: function (res) {
console.log(res);
},
complete: function (res) {},
});
},
async onOpenByMp(event: WechatMiniprogram.Touch) {
const { value } = event.currentTarget.dataset;
const fileUrl = this.features.extraFile.getUrl(value);
let extension = value.extension.toLowerCase();
let extensions = [
'doc',
'docx',
'xls',
'xlsx',
'ppt',
'pptx',
'pdf',
]; //openDocument fileType目前只支持范围
if (!extensions.includes(extension)) {
this.setMessage({
type: 'error',
content: `目前仅支持打开${extensions.join(',')}类型的文件`,
});
return;
}
wx.showLoading({
title: '下载请求中,请耐心等待..',
});
wx.downloadFile({
url: fileUrl,
success: function (res) {
const filePath = res.tempFilePath || res.filePath;
wx.hideLoading();
wx.openDocument({
//打开文件
filePath: filePath,
fileType: extension,
showMenu: true, // 是否显示右上角菜单按钮 默认为false(看自身需求,可要可不要。后期涉及到右上角分享功能)
success: function () {
console.log(`打开文件成功`);
},
fail: function (err) {
console.log(err);
},
});
},
fail: function (res) {
console.log(res);
},
complete: function (res) {},
});
},
},
observers: {

View File

@ -1,20 +1,46 @@
<view class="file-list__container oak-class">
<block wx:for="{{files}}" wx:key="index">
<block wx:if="{{item}}">
<view class="file-list__item file-list__item--{{size}} oak-item-class" style="{{itemSizePercentage?'width:'+itemSizePercentage+'padding-bottom:'+itemSizePercentage:'xxx'}}">
<oak-display data-index="{{index}}" bind:tap="onItemTapped" mode="{{mode}}" oakId="{{item.id}}" oakAutoUnmount="{{true}}" oakPath="{{oakFullpath}}.{{item.id}}" />
<view wx:if="{{!disableDelete}}" mut-bind:tap="onDeleteByMp" class="file-list__remove" data-value="{{item}}">
<l-icon name="close" color="#ffffff" size="18" />
<block wx:if="{{ theme === 'image' || theme === 'image-flow' }}">
<view class="file-list__container oak-class">
<block wx:for="{{files}}" wx:key="index">
<block wx:if="{{item}}">
<view class="file-list__item file-list__item--{{size}} oak-item-class" style="{{itemSizePercentage?'width:'+itemSizePercentage+'padding-bottom:'+itemSizePercentage:'xxx'}}">
<oak-display data-index="{{index}}" bind:tap="onItemTapped" mode="{{mode}}" oakId="{{item.id}}" oakAutoUnmount="{{true}}" oakPath="{{oakFullpath}}.{{item.id}}" />
<view wx:if="{{!disableDelete}}" mut-bind:tap="onDeleteByMp" class="file-list__remove" data-value="{{item}}">
<l-icon name="close" color="#ffffff" size="18" />
</view>
</view>
</view>
</block>
</block>
</block>
<view class="file-list__item file-list__item--add file-list__item--{{size}} oak-item-class" style="{{itemSizePercentage?'width:'+itemSizePercentage+'padding-bottom:'+itemSizePercentage:''}}" wx:if="{{!disableInsert}}" bind:tap="onPickByMp">
<view class="file-list__item-slot-wrapper">
<slot />
</view>
<view class="file-list__image--add">
<l-icon name="add" size="80" />
<view class="file-list__item file-list__item--add file-list__item--{{size}} oak-item-class" style="{{itemSizePercentage?'width:'+itemSizePercentage+'padding-bottom:'+itemSizePercentage:''}}" wx:if="{{!disableInsert}}" bind:tap="onPickByMp">
<view class="file-list__item-slot-wrapper">
<slot />
</view>
<view class="file-list__image--add">
<l-icon name="add" size="80" />
</view>
</view>
</view>
</view>
</block>
<block wx:else >
<view class="file-list-flow__container oak-class">
<view class="file-list-flow__item--add oak-item-add-class" wx:if="{{!disableInsert}}">
<l-button bind:lintap="onPickByMp" plain="{{true}}" type="default">选择文件</l-button>
</view>
<block wx:for="{{files}}" wx:key="index">
<block wx:if="{{item}}">
<view class="file-list-flow__item">
<view class="file-list-flow__item--name" mut-bind:tap="onOpenByMp" data-value="{{item}}">
{{ item.filename }}{{ item.extension ? '.' + item.extension : '' }}
</view>
<view class="file-list-flow__item--btns">
<view wx:if="{{!disableDelete}}" mut-bind:tap="onDownloadByMp" class="file-list-flow__download" data-value="{{item}}">
<l-icon name="download" size="24" />
</view>
<view wx:if="{{!disableDelete}}" mut-bind:tap="onDeleteByMp" class="file-list-flow__remove" data-value="{{item}}">
<l-icon name="delete" size="24" />
</view>
<view>
</view>
</block>
</block>
</view>
</block>

View File

@ -23,14 +23,13 @@ interface NewUploadFile extends UploadFile {
type Theme = 'file' | 'image' | 'file-flow' | 'image-flow' | 'custom';
type Theme = 'file' | 'image' | 'image-flow' | 'custom';
type ListType = 'text' | 'picture' | 'picture-card';
function getListType(theme: Theme): ListType {
const themeMap: Record<Theme, ListType> = {
file: 'text',
image: 'picture-card',
'file-flow': 'text',
'image-flow': 'picture',
custom: 'text',
};
@ -112,12 +111,15 @@ export default function render(
const extraFileToUploadFile = (
extraFile: EntityDict['extraFile']['OpSchema'],
): NewUploadFile => {
const filename =
extraFile.filename +
(extraFile.extension ? `.${extraFile.extension}` : '');
return {
id: extraFile.id,
url: features.extraFile.getUrl(extraFile),
thumbUrl: features.extraFile.getUrl(extraFile),
name: extraFile.filename + (extraFile.extension || ''),
fileName: extraFile.filename + (extraFile.extension || ''),
name: filename,
fileName: filename,
size: extraFile.size!,
type: extraFile.fileType,
uid: extraFile.id, //upload 组件需要uid来维护fileList

View File

@ -4,7 +4,7 @@ import { LocaleDef } from 'oak-domain/lib/types/Locale';
export interface Schema extends EntityShape {
origin: 'qiniu' | 'unknown';
type: 'image' | 'video' | 'audio' | 'file' | 'pdf';
type: 'image' | 'video' | 'audio' | 'file';
bucket: String<16>;
objectId: String<64>;
tag1: String<16>;
@ -57,7 +57,6 @@ const locale: LocaleDef<
video: '视频',
audio: '音频',
file: '文件',
pdf: 'pdf',
},
},
},

View File

@ -36,9 +36,7 @@ export class ExtraFile<
return uploadInfo;
}
async upload(
extraFile: EntityDict['extraFile']['CreateSingle']['data']
) {
async upload(extraFile: EntityDict['extraFile']['CreateSingle']['data']) {
const { origin, extra1, filename, objectId, extension, entity } =
extraFile;
// 构造文件上传所需的key
@ -74,6 +72,14 @@ export class ExtraFile<
return url;
}
getFileName(extraFile: EntityDict['extraFile']['OpSchema']) {
const name =
extraFile.filename +
(extraFile.extension ? `.${extraFile.extension}` : '');
return name;
}
formatBytes(size: number) {
return bytesToSize(size);
}

View File

@ -201,8 +201,12 @@ export class Token<
this.publish();
}
async getWechatMpUserPhoneNumber() {
await this.cache.exec('getWechatMpUserPhoneNumber', {});
async getWechatMpUserPhoneNumber(code: string) {
const env = await getEnv();
await this.cache.exec('getWechatMpUserPhoneNumber', {
code,
env: env as WechatMpEnv,
});
this.publish();
}
}

View File

@ -1,6 +1,10 @@
{
"navigationBarTitleText": "绑定手机号",
"usingComponents": {
"l-button": "../../../miniprogram_npm/lin-ui/button/index"
"l-button": "../../../miniprogram_npm/lin-ui/button/index",
"l-card": "../../../miniprogram_npm/lin-ui/card/index",
"l-list": "../../../miniprogram_npm/lin-ui/list/index",
"l-icon": "../../../miniprogram_npm/lin-ui/icon/index",
"l-dialog": "../../../miniprogram_npm/lin-ui/dialog/index"
}
}

View File

@ -15,3 +15,26 @@
.safe-area-inset-bottom();
}
.container {
flex: 1;
display: flex;
flex-direction: column;
}
.container2 {
flex-direction: row;
align-items: center;
justify-content: center;
}
.card {
min-width: 480rpx;
text-align: center;
}
.list {
background-color: #fff;
margin-top: 20rpx;
padding: 0 20rpx;
}

View File

@ -1,13 +1,30 @@
<!-- index.wxml -->
<view class="page-body">
<block wx:if="{{mobiles && mobiles.length > 0}}">
<view wx:for="{{mobiles}}" wx:key="index" class="card">
<text>{{item.mobile}}</text>
<view class="container">
<view class="list" wx:for="{{mobiles}}">
<l-list icon="mobile" title="{{item.mobile}}" is-link="{{false}}">
<view slot="right-section">
<view bind:tap="onRemoveModalOpen" data-id="{{item.id}}">
<l-icon name="delete" size="24" />
</view>
</view>
</l-list>
</view>
</view>
</block>
<block wx:else>
<view style="flex:1; display:flex; align-items:center;justify-content:center">尚未授权手机号</view>
</block>
<view style="display: flex; flex: 1"></view>
<l-button type="default" style="margin: 16rpx" block size="large" open-type="getPhoneNumber" bindgetphonenumber="onRefreshMobile" content="授权手机号" />
</view>
<view class="container container2">
<l-card type="primary" plaintext="{{true}}">
<view class="card">
您尚未授权手机号
</view>
</l-card>
</view>
</block>
<l-button type="default" block size="long" open-type="getPhoneNumber" bindgetphonenumber="onRefreshMobile">
授权手机号
</l-button>
</view>
<l-dialog show="{{confirmDeleteModalVisible}}" type="confirm" title="提示" content="确认删除吗?删除后无法用此号码登录" bind:linconfirm="onRemoveConfirm" bind:lincancel="onRemoveModalClose" />

View File

@ -3,6 +3,8 @@
"usingComponents": {
"l-button": "../../../miniprogram_npm/lin-ui/button/index",
"l-card": "../../../miniprogram_npm/lin-ui/card/index",
"l-list": "../../../miniprogram_npm/lin-ui/list/index"
"l-list": "../../../miniprogram_npm/lin-ui/list/index",
"l-icon": "../../../miniprogram_npm/lin-ui/icon/index",
"l-dialog": "../../../miniprogram_npm/lin-ui/dialog/index"
}
}

View File

@ -16,6 +16,11 @@
.container {
flex: 1;
display: flex;
flex-direction: column;
}
.container2 {
flex-direction: row;
align-items: center;
justify-content: center;
}
@ -26,5 +31,8 @@
}
.list {
flex: 1;
background-color: #fff;
margin-top: 20rpx;
padding: 0 20rpx;
}

View File

@ -6,6 +6,7 @@ export default OakComponent({
id: 1,
mobile: 1,
userId: 1,
ableState: 1,
},
filters: [
{
@ -76,5 +77,30 @@ export default OakComponent({
eventLoggedIn,
});
},
async onRemoveConfirm() {
const { mobileId } = this.state;
this.removeItem(mobileId);
await this.execute();
this.setState({
confirmDeleteModalVisible: false,
mobileId: '',
});
},
onRemoveModalOpen(e: WechatMiniprogram.Touch) {
const mobileId = e.currentTarget.dataset.id;
console.log(mobileId);
this.setState({
confirmDeleteModalVisible: true,
mobileId,
});
},
onRemoveModalClose() {
this.setState({
confirmDeleteModalVisible: false,
mobileId: '',
});
},
},
});

View File

@ -1,18 +1,32 @@
<!-- index.wxml -->
<view class="page-body">
<block wx:if="{{mobiles && mobiles.length > 0}}">
<view class="container">
<view class="list" wx:if="{{mobiles && mobiles.length > 0}}">
<l-list title="{{item.mobile}}" />
</view>
<block wx:else>
<l-card type="primary" plaintext="{{true}}">
<view class="card">
您尚未授权手机号
<view class="list" wx:for="{{mobiles}}">
<l-list icon="mobile" title="{{item.mobile}}" is-link="{{false}}" >
<view slot="right-section">
<view wx:if="{{allowRemove}}" bind:tap="onRemoveModalOpen" data-id="{{item.id}}">
<l-icon name="delete" size="24" />
</view>
</l-card>
</block>
</view>
</l-list>
</view>
</view>
</block>
<block wx:else>
<view class="container container2">
<l-card type="primary" plaintext="{{true}}">
<view class="card">
您尚未授权手机号
</view>
</l-card>
</view>
<l-button type="default" block size="long" open-type="getPhoneNumber" bindgetphonenumber="onRefreshMobile">
</block>
<l-button type="default" block size="long" open-type="getPhoneNumber" bindgetphonenumber="onRefreshMobile">
授权手机号
</l-button>
</view>
</l-button>
</view>
<l-dialog show="{{confirmDeleteModalVisible}}" type="confirm" title="提示" content="确认删除吗?删除后无法用此号码登录" bind:linconfirm="onRemoveConfirm" bind:lincancel="onRemoveModalClose" />