apply Network.ts
This commit is contained in:
89
miniprogram/api/JournalApi.ts
Normal file
89
miniprogram/api/JournalApi.ts
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { Network } from "../utils/Network";
|
||||||
|
import { Journal, JournalPage } from "../types/Journal";
|
||||||
|
import { QueryPageResult } from "../types/Model";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Journal 日记 API
|
||||||
|
*
|
||||||
|
* 按业务模块封装网络请求,使代码更清晰、可维护
|
||||||
|
*/
|
||||||
|
export class JournalApi {
|
||||||
|
/**
|
||||||
|
* 获取日记详情
|
||||||
|
*
|
||||||
|
* @param id - 日记 ID
|
||||||
|
*/
|
||||||
|
static getDetail(id: number | string): Promise<Journal> {
|
||||||
|
return Network.post<Journal>(`/journal/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日记分页列表
|
||||||
|
*
|
||||||
|
* @param pageParams - 分页参数
|
||||||
|
*/
|
||||||
|
static getList(pageParams: JournalPage): Promise<QueryPageResult<Journal>> {
|
||||||
|
return Network.post<QueryPageResult<Journal>>("/journal/list", pageParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建日记
|
||||||
|
*
|
||||||
|
* @param data - 日记数据
|
||||||
|
*/
|
||||||
|
static create(data: Partial<Journal> & {
|
||||||
|
pusher?: string;
|
||||||
|
tempFileIds?: string[];
|
||||||
|
}): Promise<Journal> {
|
||||||
|
return Network.post<Journal>("/journal/create", data, {
|
||||||
|
showLoading: true,
|
||||||
|
loadingText: "正在保存.."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新日记
|
||||||
|
*
|
||||||
|
* @param data - 日记数据(必须包含 id)
|
||||||
|
*/
|
||||||
|
static update(data: Partial<Journal> & {
|
||||||
|
id: number;
|
||||||
|
attachmentIds?: number[];
|
||||||
|
tempFileIds?: string[];
|
||||||
|
}): Promise<Journal> {
|
||||||
|
return Network.post<Journal>("/journal/update", data, {
|
||||||
|
showLoading: true,
|
||||||
|
loadingText: "正在保存.."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除日记
|
||||||
|
*
|
||||||
|
* @param id - 日记 ID
|
||||||
|
*/
|
||||||
|
static delete(id: number): Promise<void> {
|
||||||
|
return Network.post<void>("/journal/delete", { id }, {
|
||||||
|
showLoading: true,
|
||||||
|
loadingText: "删除中..."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 openId(用于推送)
|
||||||
|
*
|
||||||
|
* @param code - 微信登录 code
|
||||||
|
*/
|
||||||
|
static getOpenId(code: string): Promise<string> {
|
||||||
|
return Network.post<string>("/journal/openid", { code });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 ID 列表获取日记
|
||||||
|
*
|
||||||
|
* @param ids - 日记 ID 列表
|
||||||
|
*/
|
||||||
|
static getListByIds(ids: number[]): Promise<Journal[]> {
|
||||||
|
return Network.post<Journal[]>("/journal/list/ids", ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
69
miniprogram/api/MomentApi.ts
Normal file
69
miniprogram/api/MomentApi.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { Network } from "../utils/Network";
|
||||||
|
import { Attachment } from "../types/Attachment";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moment 瞬间 API
|
||||||
|
*
|
||||||
|
* 管理临时照片/视频上传、归档到日记等操作
|
||||||
|
*/
|
||||||
|
export class MomentApi {
|
||||||
|
/**
|
||||||
|
* 获取 moment 列表
|
||||||
|
*/
|
||||||
|
static getList(): Promise<Attachment[]> {
|
||||||
|
return Network.post<Attachment[]>("/journal/moment/list");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MD5 查重过滤
|
||||||
|
*
|
||||||
|
* @param md5s - MD5 值数组
|
||||||
|
* @returns 未重复的 MD5 数组
|
||||||
|
*/
|
||||||
|
static filterByMD5(md5s: string[]): Promise<string[]> {
|
||||||
|
return Network.post<string[]>("/journal/moment/filter", md5s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 moment 附件
|
||||||
|
*
|
||||||
|
* @param tempFileIds - 临时文件 ID 数组
|
||||||
|
* @returns 创建的附件列表
|
||||||
|
*/
|
||||||
|
static create(tempFileIds: string[]): Promise<Attachment[]> {
|
||||||
|
return Network.post<Attachment[]>("/journal/moment/create", tempFileIds, {
|
||||||
|
showLoading: true,
|
||||||
|
loadingText: "正在保存.."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 归档 moments 到日记
|
||||||
|
*
|
||||||
|
* @param data - 归档数据
|
||||||
|
*/
|
||||||
|
static archive(data: {
|
||||||
|
id?: number;
|
||||||
|
type: string;
|
||||||
|
idea: string;
|
||||||
|
lat?: number;
|
||||||
|
lng?: number;
|
||||||
|
location?: string;
|
||||||
|
pusher: string;
|
||||||
|
thumbIds: number[];
|
||||||
|
}): Promise<void> {
|
||||||
|
return Network.post<void>("/journal/moment/archive", data, {
|
||||||
|
showLoading: true,
|
||||||
|
loadingText: "正在归档.."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 moments
|
||||||
|
*
|
||||||
|
* @param ids - 附件 ID 数组
|
||||||
|
*/
|
||||||
|
static delete(ids: number[]): Promise<void> {
|
||||||
|
return Network.post<void>("/journal/moment/delete", ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ import Toolkit from "../../utils/Toolkit";
|
|||||||
import { ImageMetadata, MediaAttachExt, MediaAttachType } from "../../types/Attachment";
|
import { ImageMetadata, MediaAttachExt, MediaAttachType } from "../../types/Attachment";
|
||||||
import { MediaItem, MediaItemType } from "../../types/UI";
|
import { MediaItem, MediaItemType } from "../../types/UI";
|
||||||
import Time from "../../utils/Time";
|
import Time from "../../utils/Time";
|
||||||
|
import { JournalApi } from "../../api/JournalApi";
|
||||||
|
|
||||||
interface JournalDetailPanelData {
|
interface JournalDetailPanelData {
|
||||||
journals: Journal[];
|
journals: Journal[];
|
||||||
@ -35,24 +36,7 @@ Component({
|
|||||||
if (visible && ids && 0 < ids.length) {
|
if (visible && ids && 0 < ids.length) {
|
||||||
wx.showLoading({ title: "加载中...", mask: true });
|
wx.showLoading({ title: "加载中...", mask: true });
|
||||||
try {
|
try {
|
||||||
const journals: Journal[] = await new Promise((resolve, reject) => {
|
const journals = await JournalApi.getListByIds(ids);
|
||||||
wx.request({
|
|
||||||
url: `${config.url}/journal/list/ids`,
|
|
||||||
method: "POST",
|
|
||||||
header: {
|
|
||||||
Key: wx.getStorageSync("key")
|
|
||||||
},
|
|
||||||
data: ids,
|
|
||||||
success: (resp: any) => {
|
|
||||||
if (resp.data.code === 20000) {
|
|
||||||
resolve(resp.data.data);
|
|
||||||
} else {
|
|
||||||
reject(new Error(resp.data.message || "加载失败"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: reject
|
|
||||||
});
|
|
||||||
}) || [];
|
|
||||||
journals.forEach(journal => {
|
journals.forEach(journal => {
|
||||||
journal.date = Time.toPassedDate(journal.createdAt);
|
journal.date = Time.toPassedDate(journal.createdAt);
|
||||||
journal.time = Time.toTime(journal.createdAt);
|
journal.time = Time.toTime(journal.createdAt);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { JournalPage, JournalPageType } from "../../types/Journal";
|
|||||||
import { OrderType } from "../../types/Model";
|
import { OrderType } from "../../types/Model";
|
||||||
import Time from "../../utils/Time";
|
import Time from "../../utils/Time";
|
||||||
import Toolkit from "../../utils/Toolkit";
|
import Toolkit from "../../utils/Toolkit";
|
||||||
|
import { JournalApi } from "../../api/JournalApi";
|
||||||
|
|
||||||
export type JournalListItem = {
|
export type JournalListItem = {
|
||||||
id: number;
|
id: number;
|
||||||
@ -19,14 +20,10 @@ interface JournalListData {
|
|||||||
isFinished: boolean;
|
isFinished: boolean;
|
||||||
page: JournalPage;
|
page: JournalPage;
|
||||||
searchValue: string;
|
searchValue: string;
|
||||||
|
debouncedSearch?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 组件实例类型扩展
|
Component({
|
||||||
interface ComponentInstance {
|
|
||||||
debouncedSearch?: ((keyword: string) => void) & { cancel(): void };
|
|
||||||
}
|
|
||||||
|
|
||||||
Component<JournalListData, {}, {}, ComponentInstance>({
|
|
||||||
options: {
|
options: {
|
||||||
styleIsolation: 'apply-shared'
|
styleIsolation: 'apply-shared'
|
||||||
},
|
},
|
||||||
@ -64,25 +61,28 @@ Component<JournalListData, {}, {}, ComponentInstance>({
|
|||||||
createdAt: OrderType.DESC
|
createdAt: OrderType.DESC
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
searchValue: ""
|
searchValue: "",
|
||||||
|
debouncedSearch: undefined
|
||||||
},
|
},
|
||||||
lifetimes: {
|
lifetimes: {
|
||||||
ready() {
|
ready() {
|
||||||
// 创建防抖搜索函数
|
// 创建防抖搜索函数
|
||||||
this.debouncedSearch = Toolkit.debounce(
|
this.setData({
|
||||||
(keyword: string) => {
|
debouncedSearch: Toolkit.debounce(
|
||||||
this.resetAndSearch(keyword);
|
(keyword: string) => {
|
||||||
},
|
this.resetAndSearch(keyword);
|
||||||
false, // 不立即执行,等待输入停止
|
},
|
||||||
400 // 400ms 延迟
|
false, // 不立即执行,等待输入停止
|
||||||
);
|
400 // 400ms 延迟
|
||||||
|
)
|
||||||
|
})
|
||||||
// 组件加载时就获取数据
|
// 组件加载时就获取数据
|
||||||
this.fetch();
|
this.fetch();
|
||||||
},
|
},
|
||||||
detached() {
|
detached() {
|
||||||
// 组件销毁时取消防抖
|
// 组件销毁时取消防抖
|
||||||
if (this.debouncedSearch) {
|
if (this.data.debouncedSearch) {
|
||||||
this.debouncedSearch.cancel();
|
this.data.debouncedSearch.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -125,77 +125,74 @@ Component<JournalListData, {}, {}, ComponentInstance>({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
/** 获取数据 */
|
/** 获取数据 */
|
||||||
fetch() {
|
async fetch() {
|
||||||
if (this.data.isFetching || this.data.isFinished) {
|
if (this.data.isFetching || this.data.isFinished) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setData({ isFetching: true });
|
this.setData({ isFetching: true });
|
||||||
wx.request({
|
try {
|
||||||
url: `${config.url}/journal/list`,
|
const pageResult = await JournalApi.getList(this.data.page);
|
||||||
method: "POST",
|
const list = pageResult.list;
|
||||||
header: {
|
if (!list || list.length === 0) {
|
||||||
Key: wx.getStorageSync("key")
|
|
||||||
},
|
|
||||||
data: this.data.page,
|
|
||||||
success: (resp: any) => {
|
|
||||||
const list = resp.data.data.list;
|
|
||||||
if (!list || list.length === 0) {
|
|
||||||
this.setData({ isFinished: true });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const result = list.map((journal: any) => {
|
|
||||||
const firstThumb = journal.items.find((item: any) => item.attachType === "THUMB");
|
|
||||||
return {
|
|
||||||
id: journal.id,
|
|
||||||
date: Time.toPassedDate(journal.createdAt),
|
|
||||||
idea: journal.idea,
|
|
||||||
location: journal.location,
|
|
||||||
thumbUrl: firstThumb ? `${config.url}/attachment/read/${firstThumb.mongoId}` : undefined
|
|
||||||
} as JournalListItem;
|
|
||||||
});
|
|
||||||
this.setData({
|
this.setData({
|
||||||
page: {
|
isFinished: true,
|
||||||
...this.data.page,
|
isFetching: false
|
||||||
index: this.data.page.index + 1,
|
|
||||||
type: JournalPageType.PREVIEW,
|
|
||||||
equalsExample: this.data.page.equalsExample,
|
|
||||||
likeExample: this.data.page.likeExample,
|
|
||||||
orderMap: {
|
|
||||||
createdAt: OrderType.DESC
|
|
||||||
}
|
|
||||||
},
|
|
||||||
list: this.data.list.concat(result),
|
|
||||||
isFinished: list.length < this.data.page.size
|
|
||||||
});
|
});
|
||||||
},
|
return;
|
||||||
complete: () => {
|
|
||||||
this.setData({ isFetching: false });
|
|
||||||
}
|
}
|
||||||
});
|
const result = list.map((journal: any) => {
|
||||||
|
const firstThumb = journal.items.find((item: any) => item.attachType === "THUMB");
|
||||||
|
return {
|
||||||
|
id: journal.id,
|
||||||
|
date: Time.toPassedDate(journal.createdAt),
|
||||||
|
idea: journal.idea,
|
||||||
|
location: journal.location,
|
||||||
|
thumbUrl: firstThumb ? `${config.url}/attachment/read/${firstThumb.mongoId}` : undefined
|
||||||
|
} as JournalListItem;
|
||||||
|
});
|
||||||
|
this.setData({
|
||||||
|
page: {
|
||||||
|
...this.data.page,
|
||||||
|
index: this.data.page.index + 1,
|
||||||
|
type: JournalPageType.PREVIEW,
|
||||||
|
equalsExample: this.data.page.equalsExample,
|
||||||
|
likeExample: this.data.page.likeExample,
|
||||||
|
orderMap: {
|
||||||
|
createdAt: OrderType.DESC
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list: this.data.list.concat(result),
|
||||||
|
isFinished: list.length < this.data.page.size,
|
||||||
|
isFetching: false
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载日记列表失败:", error);
|
||||||
|
this.setData({ isFetching: false });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/** 输入搜索 */
|
/** 输入搜索 */
|
||||||
onSearchChange(e: WechatMiniprogram.CustomEvent) {
|
onSearchChange(e: WechatMiniprogram.CustomEvent) {
|
||||||
const value = e.detail.value.trim();
|
const value = e.detail.value.trim();
|
||||||
this.setData({ searchValue: value });
|
this.setData({ searchValue: value });
|
||||||
// 使用防抖自动搜索(包括清空的情况)
|
// 使用防抖自动搜索(包括清空的情况)
|
||||||
if (this.debouncedSearch) {
|
if (this.data.debouncedSearch) {
|
||||||
this.debouncedSearch(value);
|
this.data.debouncedSearch(value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** 提交搜索 */
|
/** 提交搜索 */
|
||||||
onSearchSubmit(e: WechatMiniprogram.CustomEvent) {
|
onSearchSubmit(e: WechatMiniprogram.CustomEvent) {
|
||||||
const value = e.detail.value.trim();
|
const value = e.detail.value.trim();
|
||||||
// 立即搜索,取消防抖
|
// 立即搜索,取消防抖
|
||||||
if (this.debouncedSearch) {
|
if (this.data.debouncedSearch) {
|
||||||
this.debouncedSearch.cancel();
|
this.data.debouncedSearch.cancel();
|
||||||
}
|
}
|
||||||
this.resetAndSearch(value);
|
this.resetAndSearch(value);
|
||||||
},
|
},
|
||||||
/** 清空搜索 */
|
/** 清空搜索 */
|
||||||
onSearchClear() {
|
onSearchClear() {
|
||||||
// 取消防抖,立即搜索
|
// 取消防抖,立即搜索
|
||||||
if (this.debouncedSearch) {
|
if (this.data.debouncedSearch) {
|
||||||
this.debouncedSearch.cancel();
|
this.data.debouncedSearch.cancel();
|
||||||
}
|
}
|
||||||
this.resetAndSearch("");
|
this.resetAndSearch("");
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// components/travel-location-popup/index.ts
|
// components/travel-location-popup/index.ts
|
||||||
import { TravelLocation, TravelLocationTypeLabel, TravelLocationTypeIcon } from "../../types/Travel";
|
import { TravelLocation, TravelLocationTypeLabel, TravelLocationTypeIcon } from "../../types/Travel";
|
||||||
import { TravelLocationApi } from "../../api/TravelLocationApi";
|
import { TravelLocationApi } from "../../api/TravelLocationApi";
|
||||||
import { MediaAttachExt, MediaAttachType } from "../../types/Attachment";
|
import { ImageMetadata, MediaAttachType } from "../../types/Attachment";
|
||||||
import { MediaItem, MediaItemType } from "../../types/UI";
|
import { MediaItem, MediaItemType } from "../../types/UI";
|
||||||
import config from "../../config/index";
|
import config from "../../config/index";
|
||||||
import Toolkit from "../../utils/Toolkit";
|
import Toolkit from "../../utils/Toolkit";
|
||||||
@ -39,11 +39,11 @@ Component({
|
|||||||
|
|
||||||
// 处理附件数据
|
// 处理附件数据
|
||||||
const attachments = location.items || [];
|
const attachments = location.items || [];
|
||||||
const thumbItems = attachments.filter((item: any) => item.attachType === MediaAttachType.THUMB);
|
const thumbItems = attachments.filter(item => item.attachType === MediaAttachType.THUMB);
|
||||||
|
|
||||||
if (0 < thumbItems.length) {
|
if (0 < thumbItems.length) {
|
||||||
const mediaItems: MediaItem[] = thumbItems.map((thumbItem: any, index: number) => {
|
const mediaItems: MediaItem[] = thumbItems.map((thumbItem, index) => {
|
||||||
const metadata = thumbItem.metadata;
|
const metadata = thumbItem.metadata as ImageMetadata;
|
||||||
const ext = typeof thumbItem.ext === "string" ? JSON.parse(thumbItem.ext) : thumbItem.ext;
|
const ext = typeof thumbItem.ext === "string" ? JSON.parse(thumbItem.ext) : thumbItem.ext;
|
||||||
const thumbURL = `${config.url}/attachment/read/${thumbItem.mongoId}`;
|
const thumbURL = `${config.url}/attachment/read/${thumbItem.mongoId}`;
|
||||||
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import config from "../../config/index"
|
import config from "../../config/index"
|
||||||
import { JournalPage, JournalPageType } from "../../types/Journal";
|
import { JournalPage, JournalPageType } from "../../types/Journal";
|
||||||
|
import { JournalApi } from "../../api/JournalApi";
|
||||||
|
|
||||||
interface IndexData {
|
interface IndexData {
|
||||||
key: string;
|
key: string;
|
||||||
@ -19,32 +20,23 @@ Page({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
navigateToMain() {
|
async navigateToMain() {
|
||||||
wx.request({
|
try {
|
||||||
url: `${config.url}/journal/list`,
|
await JournalApi.getList({
|
||||||
method: "POST",
|
|
||||||
header: {
|
|
||||||
Key: this.data.key
|
|
||||||
},
|
|
||||||
data: <JournalPage> {
|
|
||||||
index: 0,
|
index: 0,
|
||||||
size: 1,
|
size: 1,
|
||||||
type: JournalPageType.PREVIEW
|
type: JournalPageType.PREVIEW
|
||||||
},
|
});
|
||||||
success: (resp) => {
|
wx.setStorageSync("key", this.data.key);
|
||||||
const data = resp.data as any;
|
wx.switchTab({
|
||||||
if (data.code === 20000) {
|
url: "/pages/main/journal/index",
|
||||||
wx.setStorageSync("key", this.data.key);
|
})
|
||||||
wx.switchTab({
|
} catch (error: any) {
|
||||||
url: "/pages/main/journal/index",
|
if (error?.code === 40100) {
|
||||||
})
|
wx.showToast({ title: "密码错误", icon: "error" });
|
||||||
} else if (data.code === 40100) {
|
} else {
|
||||||
wx.showToast({ title: "密码错误", icon: "error" });
|
wx.showToast({ title: "验证失败", icon: "error" });
|
||||||
} else {
|
}
|
||||||
wx.showToast({ title: "服务异常", icon: "error" });
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: () => wx.showToast({ title: "验证失败", icon: "error" })
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// pages/main/journal-date/index.ts
|
// pages/main/journal-date/index.ts
|
||||||
import config from "../../../config/index";
|
|
||||||
import { Journal, JournalPageType } from "../../../types/Journal";
|
import { Journal, JournalPageType } from "../../../types/Journal";
|
||||||
import Time from "../../../utils/Time";
|
import Time from "../../../utils/Time";
|
||||||
|
import { JournalApi } from "../../../api/JournalApi";
|
||||||
|
|
||||||
interface JournalDateData {
|
interface JournalDateData {
|
||||||
// 存储每个日期的日记 id 列表
|
// 存储每个日期的日记 id 列表
|
||||||
@ -27,28 +27,12 @@ Page({
|
|||||||
async loadJournals() {
|
async loadJournals() {
|
||||||
this.setData({ isLoading: true });
|
this.setData({ isLoading: true });
|
||||||
try {
|
try {
|
||||||
const list: Journal[] = await new Promise((resolve, reject) => {
|
const pageResult = await JournalApi.getList({
|
||||||
wx.request({
|
index: 0,
|
||||||
url: `${config.url}/journal/list`,
|
size: 9007199254740992,
|
||||||
method: "POST",
|
type: JournalPageType.PREVIEW
|
||||||
header: {
|
});
|
||||||
Key: wx.getStorageSync("key")
|
const list: Journal[] = pageResult.list || [];
|
||||||
},
|
|
||||||
data: {
|
|
||||||
page: 0,
|
|
||||||
size: 9007199254740992,
|
|
||||||
type: JournalPageType.PREVIEW
|
|
||||||
},
|
|
||||||
success: (resp: any) => {
|
|
||||||
if (resp.data.code === 20000) {
|
|
||||||
resolve(resp.data.data.list);
|
|
||||||
} else {
|
|
||||||
reject(new Error(resp.data.message || "加载失败"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: reject
|
|
||||||
});
|
|
||||||
}) || [];
|
|
||||||
// 按日期分组,只存储 id
|
// 按日期分组,只存储 id
|
||||||
const journalMap: Record<string, number[]> = {};
|
const journalMap: Record<string, number[]> = {};
|
||||||
list.forEach((journal: any) => {
|
list.forEach((journal: any) => {
|
||||||
|
|||||||
@ -4,9 +4,10 @@ import Time from "../../../utils/Time";
|
|||||||
import Toolkit from "../../../utils/Toolkit";
|
import Toolkit from "../../../utils/Toolkit";
|
||||||
import config from "../../../config/index";
|
import config from "../../../config/index";
|
||||||
import { Location, MediaItem, MediaItemType, WechatMediaItem } from "../../../types/UI";
|
import { Location, MediaItem, MediaItemType, WechatMediaItem } from "../../../types/UI";
|
||||||
import { Journal, JournalType } from "../../../types/Journal";
|
import { JournalType } from "../../../types/Journal";
|
||||||
import { MediaAttachExt, MediaAttachType } from "../../../types/Attachment";
|
import { MediaAttachExt, MediaAttachType } from "../../../types/Attachment";
|
||||||
import IOSize, { Unit } from "../../../utils/IOSize";
|
import IOSize, { Unit } from "../../../utils/IOSize";
|
||||||
|
import { JournalApi } from "../../../api/JournalApi";
|
||||||
|
|
||||||
interface JournalEditorData {
|
interface JournalEditorData {
|
||||||
/** 模式:create 或 edit */
|
/** 模式:create 或 edit */
|
||||||
@ -148,25 +149,8 @@ Page({
|
|||||||
},
|
},
|
||||||
/** 加载日记详情(编辑模式) */
|
/** 加载日记详情(编辑模式) */
|
||||||
async loadJournalDetail(id: number) {
|
async loadJournalDetail(id: number) {
|
||||||
wx.showLoading({ title: "加载中...", mask: true });
|
|
||||||
try {
|
try {
|
||||||
const journal: Journal = await new Promise((resolve, reject) => {
|
const journal = await JournalApi.getDetail(id);
|
||||||
wx.request({
|
|
||||||
url: `${config.url}/journal/${id}`,
|
|
||||||
method: "POST",
|
|
||||||
header: {
|
|
||||||
Key: wx.getStorageSync("key")
|
|
||||||
},
|
|
||||||
success: (res: any) => {
|
|
||||||
if (res.data.code === 20000) {
|
|
||||||
resolve(res.data.data);
|
|
||||||
} else {
|
|
||||||
reject(new Error(res.data.message || "加载失败"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: reject
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const items = journal.items || [];
|
const items = journal.items || [];
|
||||||
const thumbItems = items.filter((item) => item.attachType === MediaAttachType.THUMB);
|
const thumbItems = items.filter((item) => item.attachType === MediaAttachType.THUMB);
|
||||||
@ -309,11 +293,11 @@ Page({
|
|||||||
// 编辑模式:mediaList + newMediaList
|
// 编辑模式:mediaList + newMediaList
|
||||||
const sources = (this.data.mediaList as MediaItem[]).map(item => ({
|
const sources = (this.data.mediaList as MediaItem[]).map(item => ({
|
||||||
url: item.sourceURL,
|
url: item.sourceURL,
|
||||||
type: MediaItemType[item.type].toLowerCase()
|
type: item.type
|
||||||
}));
|
}));
|
||||||
const newSources = this.data.newMediaList.map(item => ({
|
const newSources = this.data.newMediaList.map(item => ({
|
||||||
url: item.path,
|
url: item.path,
|
||||||
type: MediaItemType[item.type].toLowerCase()
|
type: item.type
|
||||||
}));
|
}));
|
||||||
const allSources = [...sources, ...newSources];
|
const allSources = [...sources, ...newSources];
|
||||||
const itemIndex = isNewMedia ? this.data.mediaList.length + index : index;
|
const itemIndex = isNewMedia ? this.data.mediaList.length + index : index;
|
||||||
@ -392,45 +376,21 @@ Page({
|
|||||||
this.executeDelete();
|
this.executeDelete();
|
||||||
},
|
},
|
||||||
/** 执行删除 */
|
/** 执行删除 */
|
||||||
executeDelete() {
|
async executeDelete() {
|
||||||
wx.showLoading({ title: "删除中...", mask: true });
|
try {
|
||||||
wx.request({
|
await JournalApi.delete(this.data.id!);
|
||||||
url: `${config.url}/journal/delete`,
|
Events.emit("JOURNAL_REFRESH");
|
||||||
method: "POST",
|
Events.emit("JOURNAL_LIST_REFRESH");
|
||||||
header: {
|
wx.showToast({
|
||||||
Key: wx.getStorageSync("key"),
|
title: "删除成功",
|
||||||
"Content-Type": "application/json"
|
icon: "success"
|
||||||
},
|
});
|
||||||
data: {
|
setTimeout(() => {
|
||||||
id: this.data.id
|
wx.navigateBack();
|
||||||
},
|
}, 1000);
|
||||||
success: (res: any) => {
|
} catch (error) {
|
||||||
wx.hideLoading();
|
console.error("删除日记失败:", error);
|
||||||
if (res.data.code === 20000 || res.statusCode === 200) {
|
}
|
||||||
Events.emit("JOURNAL_REFRESH");
|
|
||||||
Events.emit("JOURNAL_LIST_REFRESH");
|
|
||||||
wx.showToast({
|
|
||||||
title: "删除成功",
|
|
||||||
icon: "success"
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
wx.navigateBack();
|
|
||||||
}, 1000);
|
|
||||||
} else {
|
|
||||||
wx.showToast({
|
|
||||||
title: res.data.message || "删除失败",
|
|
||||||
icon: "error"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
wx.hideLoading();
|
|
||||||
wx.showToast({
|
|
||||||
title: "删除失败",
|
|
||||||
icon: "error"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
/** 提交/保存 */
|
/** 提交/保存 */
|
||||||
submit() {
|
submit() {
|
||||||
@ -441,10 +401,9 @@ Page({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** 创建日记 */
|
/** 创建日记 */
|
||||||
createJournal() {
|
async createJournal() {
|
||||||
const handleFail = () => {
|
const handleFail = () => {
|
||||||
wx.showToast({ title: "上传失败", icon: "error" });
|
wx.showToast({ title: "上传失败", icon: "error" });
|
||||||
wx.hideLoading();
|
|
||||||
this.setData({
|
this.setData({
|
||||||
isSaving: false
|
isSaving: false
|
||||||
});
|
});
|
||||||
@ -452,83 +411,64 @@ Page({
|
|||||||
this.setData({
|
this.setData({
|
||||||
isSaving: true
|
isSaving: true
|
||||||
});
|
});
|
||||||
// 获取 openId
|
try {
|
||||||
const getOpenId = new Promise<string>((resolve, reject) => {
|
// 获取 openId
|
||||||
wx.login({
|
const getOpenId = new Promise<string>((resolve, reject) => {
|
||||||
success: (res) => {
|
wx.login({
|
||||||
if (res.code) {
|
success: async (res) => {
|
||||||
wx.request({
|
if (res.code) {
|
||||||
url: `${config.url}/journal/openid`,
|
try {
|
||||||
method: "POST",
|
const openId = await JournalApi.getOpenId(res.code);
|
||||||
header: {
|
resolve(openId);
|
||||||
Key: wx.getStorageSync("key")
|
} catch (error) {
|
||||||
},
|
reject(new Error("获取 openId 失败"));
|
||||||
data: {
|
}
|
||||||
code: res.code
|
} else {
|
||||||
},
|
reject(new Error("获取登录凭证失败"));
|
||||||
success: (resp) => {
|
}
|
||||||
const data = resp.data as any;
|
},
|
||||||
if (data.code === 20000) {
|
fail: () => reject(new Error("登录失败"))
|
||||||
resolve(data.data);
|
});
|
||||||
} else {
|
|
||||||
reject(new Error("获取 openId 失败"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: () => reject(new Error("获取 openId 请求失败"))
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
reject(new Error("获取登录凭证失败"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: () => reject(new Error("登录失败"))
|
|
||||||
});
|
});
|
||||||
});
|
// 文件上传
|
||||||
// 文件上传
|
const uploadFiles = this.uploadMediaFiles(this.data.mediaList as WechatMediaItem[]);
|
||||||
const uploadFiles = this.uploadMediaFiles(this.data.mediaList as WechatMediaItem[]);
|
// 并行执行获取 openId 和文件上传
|
||||||
// 并行执行获取 openId 和文件上传
|
const [openId, tempFileIds] = await Promise.all([getOpenId, uploadFiles]);
|
||||||
Promise.all([getOpenId, uploadFiles]).then(([openId, tempFileIds]) => {
|
|
||||||
wx.showLoading({ title: "正在保存..", mask: true });
|
await JournalApi.create({
|
||||||
wx.request({
|
idea: this.data.idea,
|
||||||
url: `${config.url}/journal/create`,
|
type: this.data.type,
|
||||||
method: "POST",
|
lat: this.data.location?.lat,
|
||||||
header: {
|
lng: this.data.location?.lng,
|
||||||
Key: wx.getStorageSync("key")
|
location: this.data.location?.text,
|
||||||
},
|
pusher: openId,
|
||||||
data: {
|
createdAt: Date.parse(`${this.data.date} ${this.data.time}`),
|
||||||
idea: this.data.idea,
|
tempFileIds
|
||||||
type: this.data.type,
|
|
||||||
lat: this.data.location?.lat,
|
|
||||||
lng: this.data.location?.lng,
|
|
||||||
location: this.data.location?.text,
|
|
||||||
pusher: openId,
|
|
||||||
createdAt: Date.parse(`${this.data.date} ${this.data.time}`),
|
|
||||||
tempFileIds
|
|
||||||
},
|
|
||||||
success: async () => {
|
|
||||||
Events.emit("JOURNAL_REFRESH");
|
|
||||||
wx.showToast({ title: "提交成功", icon: "success" });
|
|
||||||
this.setData({
|
|
||||||
idea: "",
|
|
||||||
mediaList: [],
|
|
||||||
isSaving: false,
|
|
||||||
uploaded: "0",
|
|
||||||
uploadTotal: "0 MB",
|
|
||||||
uploadProgress: 0
|
|
||||||
});
|
|
||||||
await Toolkit.sleep(1000);
|
|
||||||
wx.switchTab({
|
|
||||||
url: "/pages/main/journal/index"
|
|
||||||
});
|
|
||||||
},
|
|
||||||
fail: handleFail
|
|
||||||
});
|
});
|
||||||
}).catch(handleFail);
|
|
||||||
|
Events.emit("JOURNAL_REFRESH");
|
||||||
|
wx.showToast({ title: "提交成功", icon: "success" });
|
||||||
|
this.setData({
|
||||||
|
idea: "",
|
||||||
|
mediaList: [],
|
||||||
|
isSaving: false,
|
||||||
|
uploaded: "0",
|
||||||
|
uploadTotal: "0 MB",
|
||||||
|
uploadProgress: 0
|
||||||
|
});
|
||||||
|
await Toolkit.sleep(1000);
|
||||||
|
wx.switchTab({
|
||||||
|
url: "/pages/main/journal/index"
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("创建日记失败:", error);
|
||||||
|
handleFail();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/** 更新日记 */
|
/** 更新日记 */
|
||||||
updateJournal() {
|
async updateJournal() {
|
||||||
const handleFail = () => {
|
const handleFail = () => {
|
||||||
wx.showToast({ title: "保存失败", icon: "error" });
|
wx.showToast({ title: "保存失败", icon: "error" });
|
||||||
wx.hideLoading();
|
|
||||||
this.setData({
|
this.setData({
|
||||||
isSaving: false
|
isSaving: false
|
||||||
});
|
});
|
||||||
@ -536,53 +476,39 @@ Page({
|
|||||||
this.setData({
|
this.setData({
|
||||||
isSaving: true
|
isSaving: true
|
||||||
});
|
});
|
||||||
// 收集保留的附件 ID(缩略图 ID)
|
try {
|
||||||
const attachmentIds = (this.data.mediaList as MediaItem[]).map(item => item.attachmentId);
|
// 收集保留的附件 ID(缩略图 ID)
|
||||||
// 上传新媒体文件
|
const attachmentIds = (this.data.mediaList as MediaItem[]).map(item => item.attachmentId);
|
||||||
const uploadFiles = this.uploadMediaFiles(this.data.newMediaList);
|
// 上传新媒体文件
|
||||||
|
const tempFileIds = await this.uploadMediaFiles(this.data.newMediaList);
|
||||||
|
|
||||||
// 提交保存
|
await JournalApi.update({
|
||||||
uploadFiles.then((tempFileIds) => {
|
id: this.data.id!,
|
||||||
wx.showLoading({ title: "正在保存..", mask: true });
|
idea: this.data.idea,
|
||||||
wx.request({
|
type: this.data.type,
|
||||||
url: `${config.url}/journal/update`,
|
lat: this.data.location?.lat,
|
||||||
method: "POST",
|
lng: this.data.location?.lng,
|
||||||
header: {
|
location: this.data.location?.text,
|
||||||
Key: wx.getStorageSync("key")
|
createdAt: new Date(`${this.data.date}T${this.data.time}:00`).getTime(),
|
||||||
},
|
attachmentIds,
|
||||||
data: {
|
tempFileIds
|
||||||
id: this.data.id,
|
|
||||||
idea: this.data.idea,
|
|
||||||
type: this.data.type,
|
|
||||||
lat: this.data.location?.lat,
|
|
||||||
lng: this.data.location?.lng,
|
|
||||||
location: this.data.location?.text,
|
|
||||||
createdAt: new Date(`${this.data.date}T${this.data.time}:00`).getTime(),
|
|
||||||
// 保留的现有附件 ID
|
|
||||||
attachmentIds,
|
|
||||||
// 新上传的临时文件 ID
|
|
||||||
tempFileIds
|
|
||||||
},
|
|
||||||
success: async (resp: any) => {
|
|
||||||
if (resp.data.code === 20000 || resp.statusCode === 200) {
|
|
||||||
Events.emit("JOURNAL_REFRESH");
|
|
||||||
Events.emit("JOURNAL_LIST_REFRESH");
|
|
||||||
wx.showToast({ title: "保存成功", icon: "success" });
|
|
||||||
this.setData({
|
|
||||||
isSaving: false,
|
|
||||||
uploaded: "0",
|
|
||||||
uploadTotal: "0 MB",
|
|
||||||
uploadProgress: 0
|
|
||||||
});
|
|
||||||
await Toolkit.sleep(1000);
|
|
||||||
wx.navigateBack();
|
|
||||||
} else {
|
|
||||||
handleFail();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: handleFail
|
|
||||||
});
|
});
|
||||||
}).catch(handleFail);
|
|
||||||
|
Events.emit("JOURNAL_REFRESH");
|
||||||
|
Events.emit("JOURNAL_LIST_REFRESH");
|
||||||
|
wx.showToast({ title: "保存成功", icon: "success" });
|
||||||
|
this.setData({
|
||||||
|
isSaving: false,
|
||||||
|
uploaded: "0",
|
||||||
|
uploadTotal: "0 MB",
|
||||||
|
uploadProgress: 0
|
||||||
|
});
|
||||||
|
await Toolkit.sleep(1000);
|
||||||
|
wx.navigateBack();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("更新日记失败:", error);
|
||||||
|
handleFail();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/** 上传媒体文件 */
|
/** 上传媒体文件 */
|
||||||
uploadMediaFiles(mediaList: WechatMediaItem[]): Promise<string[]> {
|
uploadMediaFiles(mediaList: WechatMediaItem[]): Promise<string[]> {
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
// pages/main/journal-map/index.ts
|
// pages/main/journal-map/index.ts
|
||||||
import config from "../../../config/index";
|
import config from "../../../config/index";
|
||||||
import Time from "../../../utils/Time";
|
import Time from "../../../utils/Time";
|
||||||
import { Journal, JournalPageType } from "../../../types/Journal";
|
import { JournalPageType } from "../../../types/Journal";
|
||||||
import Toolkit from "../../../utils/Toolkit";
|
import Toolkit from "../../../utils/Toolkit";
|
||||||
import { MapMarker } from "../../../types/UI";
|
import { MapMarker } from "../../../types/UI";
|
||||||
|
import { JournalApi } from "../../../api/JournalApi";
|
||||||
|
|
||||||
interface LocationMarker {
|
interface LocationMarker {
|
||||||
locationKey: string; // 位置键 "lat,lng"
|
locationKey: string; // 位置键 "lat,lng"
|
||||||
@ -50,28 +51,12 @@ Page({
|
|||||||
async loadJournals() {
|
async loadJournals() {
|
||||||
this.setData({ isLoading: true });
|
this.setData({ isLoading: true });
|
||||||
try {
|
try {
|
||||||
const list: Journal[] = await new Promise((resolve, reject) => {
|
const result = await JournalApi.getList({
|
||||||
wx.request({
|
index: 0,
|
||||||
url: `${config.url}/journal/list`,
|
size: 9007199254740992,
|
||||||
method: "POST",
|
type: JournalPageType.PREVIEW
|
||||||
header: {
|
});
|
||||||
Key: wx.getStorageSync("key")
|
const list = result.list || [];
|
||||||
},
|
|
||||||
data: {
|
|
||||||
page: 0,
|
|
||||||
size: 9007199254740992,
|
|
||||||
type: JournalPageType.PREVIEW
|
|
||||||
},
|
|
||||||
success: (resp: any) => {
|
|
||||||
if (resp.data.code === 20000) {
|
|
||||||
resolve(resp.data.data.list);
|
|
||||||
} else {
|
|
||||||
reject(new Error(resp.data.message || "加载失败"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: reject
|
|
||||||
});
|
|
||||||
}) || [];
|
|
||||||
// 过滤有位置信息的记录,并按位置分组
|
// 过滤有位置信息的记录,并按位置分组
|
||||||
const locationMap = new Map<string, LocationMarker>();
|
const locationMap = new Map<string, LocationMarker>();
|
||||||
list.filter((journal: any) => journal.lat && journal.lng).forEach((journal: any) => {
|
list.filter((journal: any) => journal.lat && journal.lng).forEach((journal: any) => {
|
||||||
|
|||||||
@ -5,9 +5,10 @@ import config from "../../../config/index"
|
|||||||
import Events from "../../../utils/Events";
|
import Events from "../../../utils/Events";
|
||||||
import Toolkit from "../../../utils/Toolkit";
|
import Toolkit from "../../../utils/Toolkit";
|
||||||
import { Journal, JournalPage, JournalPageType } from "../../../types/Journal";
|
import { Journal, JournalPage, JournalPageType } from "../../../types/Journal";
|
||||||
import { OrderType, QueryPageResult } from "../../../types/Model";
|
import { OrderType } from "../../../types/Model";
|
||||||
import { ImageMetadata, MediaAttachExt } from "../../../types/Attachment";
|
import { ImageMetadata, MediaAttachExt } from "../../../types/Attachment";
|
||||||
import { MediaItem, MediaItemType } from "../../../types/UI";
|
import { MediaItem, MediaItemType } from "../../../types/UI";
|
||||||
|
import { JournalApi } from "../../../api/JournalApi";
|
||||||
|
|
||||||
interface JournalData {
|
interface JournalData {
|
||||||
page: JournalPage;
|
page: JournalPage;
|
||||||
@ -143,79 +144,71 @@ Page({
|
|||||||
url: "/pages/main/journal-date/index"
|
url: "/pages/main/journal-date/index"
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetch() {
|
async fetch() {
|
||||||
if (this.data.isFetching || this.data.isFinished) {
|
if (this.data.isFetching || this.data.isFinished) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setData({
|
this.setData({
|
||||||
isFetching: true
|
isFetching: true
|
||||||
});
|
});
|
||||||
wx.request({
|
try {
|
||||||
url: `${config.url}/journal/list`,
|
const pageResult = await JournalApi.getList(this.data.page);
|
||||||
method: "POST",
|
const list = pageResult.list;
|
||||||
header: {
|
if (!list || list.length === 0) {
|
||||||
Key: wx.getStorageSync("key")
|
|
||||||
},
|
|
||||||
data: this.data.page,
|
|
||||||
success: async (resp: any) => {
|
|
||||||
const pageResult = resp.data.data as QueryPageResult<Journal>;
|
|
||||||
const list = pageResult.list;
|
|
||||||
if (!list || list.length === 0) {
|
|
||||||
this.setData({
|
|
||||||
isFinished: true
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
list.forEach(journal => {
|
|
||||||
const mediaItems = journal.items!.filter((item) => item.attachType === "THUMB").map((thumbItem, index) => {
|
|
||||||
const metadata = thumbItem.metadata as ImageMetadata;
|
|
||||||
const ext = thumbItem.ext = JSON.parse(thumbItem.ext!.toString()) as MediaAttachExt;
|
|
||||||
const thumbURL = `${config.url}/attachment/read/${thumbItem.mongoId}`;
|
|
||||||
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
|
||||||
return {
|
|
||||||
type: ext.isVideo ? MediaItemType.VIDEO : MediaItemType.IMAGE,
|
|
||||||
thumbURL,
|
|
||||||
sourceURL,
|
|
||||||
size: thumbItem.size || 0,
|
|
||||||
attachmentId: thumbItem.id,
|
|
||||||
width: metadata.width,
|
|
||||||
height: metadata.height,
|
|
||||||
originalIndex: index
|
|
||||||
} as MediaItem;
|
|
||||||
});
|
|
||||||
journal.date = Time.toDate(journal.createdAt);
|
|
||||||
journal.time = Time.toTime(journal.createdAt);
|
|
||||||
journal.datetime = Time.toPassedDateTime(journal.createdAt);
|
|
||||||
journal.mediaItems = mediaItems;
|
|
||||||
journal.columnedItems = Toolkit.splitItemsIntoColumns(mediaItems, 3, (item) => {
|
|
||||||
if (item.width && item.height && 0 < item.width) {
|
|
||||||
return item.height / item.width;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
})
|
|
||||||
})
|
|
||||||
this.setData({
|
|
||||||
page: {
|
|
||||||
index: this.data.page.index + 1,
|
|
||||||
size: 8,
|
|
||||||
type: JournalPageType.NORMAL,
|
|
||||||
equalsExample: {
|
|
||||||
type: "NORMAL"
|
|
||||||
},
|
|
||||||
orderMap: {
|
|
||||||
createdAt: OrderType.DESC
|
|
||||||
}
|
|
||||||
},
|
|
||||||
list: this.data.list.concat(list),
|
|
||||||
isFinished: list.length < this.data.page.size
|
|
||||||
});
|
|
||||||
},
|
|
||||||
complete: () => {
|
|
||||||
this.setData({
|
this.setData({
|
||||||
|
isFinished: true,
|
||||||
isFetching: false
|
isFetching: false
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
list.forEach(journal => {
|
||||||
|
const mediaItems = journal.items!.filter((item) => item.attachType === "THUMB").map((thumbItem, index) => {
|
||||||
|
const metadata = thumbItem.metadata as ImageMetadata;
|
||||||
|
const ext = thumbItem.ext = JSON.parse(thumbItem.ext!.toString()) as MediaAttachExt;
|
||||||
|
const thumbURL = `${config.url}/attachment/read/${thumbItem.mongoId}`;
|
||||||
|
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
||||||
|
return {
|
||||||
|
type: ext.isVideo ? MediaItemType.VIDEO : MediaItemType.IMAGE,
|
||||||
|
thumbURL,
|
||||||
|
sourceURL,
|
||||||
|
size: thumbItem.size || 0,
|
||||||
|
attachmentId: thumbItem.id,
|
||||||
|
width: metadata.width,
|
||||||
|
height: metadata.height,
|
||||||
|
originalIndex: index
|
||||||
|
} as MediaItem;
|
||||||
|
});
|
||||||
|
journal.date = Time.toDate(journal.createdAt);
|
||||||
|
journal.time = Time.toTime(journal.createdAt);
|
||||||
|
journal.datetime = Time.toPassedDateTime(journal.createdAt);
|
||||||
|
journal.mediaItems = mediaItems;
|
||||||
|
journal.columnedItems = Toolkit.splitItemsIntoColumns(mediaItems, 3, (item) => {
|
||||||
|
if (item.width && item.height && 0 < item.width) {
|
||||||
|
return item.height / item.width;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
this.setData({
|
||||||
|
page: {
|
||||||
|
index: this.data.page.index + 1,
|
||||||
|
size: 8,
|
||||||
|
type: JournalPageType.NORMAL,
|
||||||
|
equalsExample: {
|
||||||
|
type: "NORMAL"
|
||||||
|
},
|
||||||
|
orderMap: {
|
||||||
|
createdAt: OrderType.DESC
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list: this.data.list.concat(list),
|
||||||
|
isFinished: list.length < this.data.page.size,
|
||||||
|
isFetching: false
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载日记失败:", error);
|
||||||
|
this.setData({ isFetching: false });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
preview(e: WechatMiniprogram.BaseEvent) {
|
preview(e: WechatMiniprogram.BaseEvent) {
|
||||||
const { journalIndex, itemIndex } = e.currentTarget.dataset;
|
const { journalIndex, itemIndex } = e.currentTarget.dataset;
|
||||||
|
|||||||
@ -6,6 +6,9 @@ import Time from "../../../utils/Time";
|
|||||||
import Toolkit from "../../../utils/Toolkit";
|
import Toolkit from "../../../utils/Toolkit";
|
||||||
import { Location, MediaItemType } from "../../../types/UI";
|
import { Location, MediaItemType } from "../../../types/UI";
|
||||||
import { MediaAttachExt } from "../../../types/Attachment";
|
import { MediaAttachExt } from "../../../types/Attachment";
|
||||||
|
import { MomentApi } from "../../../api/MomentApi";
|
||||||
|
import { JournalApi } from "../../../api/JournalApi";
|
||||||
|
import { Network } from "../../../utils/Network";
|
||||||
|
|
||||||
type Item = {
|
type Item = {
|
||||||
id: number;
|
id: number;
|
||||||
@ -123,34 +126,29 @@ Page({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
fetch() {
|
async fetch() {
|
||||||
wx.request({
|
try {
|
||||||
url: `${config.url}/journal/moment/list`,
|
const list = await MomentApi.getList();
|
||||||
method: "POST",
|
if (!list || list.length === 0) {
|
||||||
header: {
|
return;
|
||||||
Key: wx.getStorageSync("key")
|
|
||||||
},
|
|
||||||
success: async (resp: any) => {
|
|
||||||
const list = resp.data.data;
|
|
||||||
if (!list || list.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.setData({
|
|
||||||
list: list.map((item: any) => {
|
|
||||||
const ext = JSON.parse(item.ext) as MediaAttachExt;
|
|
||||||
const thumbURL = `${config.url}/attachment/read/${item.mongoId}`;
|
|
||||||
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
|
||||||
return {
|
|
||||||
id: item.id,
|
|
||||||
type: ext.isImage ? MediaItemType.IMAGE : MediaItemType.VIDEO,
|
|
||||||
thumbURL,
|
|
||||||
sourceURL,
|
|
||||||
checked: false
|
|
||||||
} as Item;
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
this.setData({
|
||||||
|
list: list.map((item: any) => {
|
||||||
|
const ext = JSON.parse(item.ext) as MediaAttachExt;
|
||||||
|
const thumbURL = `${config.url}/attachment/read/${item.mongoId}`;
|
||||||
|
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
type: ext.isImage ? MediaItemType.IMAGE : MediaItemType.VIDEO,
|
||||||
|
thumbURL,
|
||||||
|
sourceURL,
|
||||||
|
checked: false
|
||||||
|
} as Item;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载 moment 列表失败:", error);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateHasChecked() {
|
updateHasChecked() {
|
||||||
this.setData({ hasChecked: this.data.list.some(item => item.checked) });
|
this.setData({ hasChecked: this.data.list.some(item => item.checked) });
|
||||||
@ -226,155 +224,65 @@ Page({
|
|||||||
} as MD5Result);
|
} as MD5Result);
|
||||||
}));
|
}));
|
||||||
// 查重
|
// 查重
|
||||||
const filterMD5Result: string[] = await new Promise((resolve, reject) => {
|
const filterMD5Result: string[] = await MomentApi.filterByMD5(
|
||||||
wx.request({
|
md5Results.map(item => item.md5)
|
||||||
url: `${config.url}/journal/moment/filter`,
|
);
|
||||||
method: "POST",
|
|
||||||
header: {
|
|
||||||
Key: wx.getStorageSync("key")
|
|
||||||
},
|
|
||||||
data: md5Results.map(item => item.md5),
|
|
||||||
success: async (resp: any) => {
|
|
||||||
resolve(resp.data.data);
|
|
||||||
},
|
|
||||||
fail: reject
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// 过滤文件
|
// 过滤文件
|
||||||
const filterPath = md5Results.filter(item => filterMD5Result.indexOf(item.md5) !== -1)
|
const filterPath = md5Results.filter(item => filterMD5Result.indexOf(item.md5) !== -1)
|
||||||
.map(item => item.path);
|
.map(item => item.path);
|
||||||
files = files.filter(file => filterPath.indexOf(file.tempFilePath) !== -1);
|
files = files.filter(file => filterPath.indexOf(file.tempFilePath) !== -1);
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
wx.hideLoading();
|
wx.hideLoading();
|
||||||
|
that.setData({ isUploading: false });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wx.showLoading({
|
|
||||||
title: "正在上传..",
|
|
||||||
mask: true
|
|
||||||
})
|
|
||||||
// 计算上传大小
|
|
||||||
const sizePromises = files.map(file => {
|
|
||||||
return new Promise<number>((sizeResolve, sizeReject) => {
|
|
||||||
wx.getFileSystemManager().getFileInfo({
|
|
||||||
filePath: file.tempFilePath,
|
|
||||||
success: (res) => sizeResolve(res.size),
|
|
||||||
fail: (err) => sizeReject(err)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Promise.all(sizePromises).then(fileSizes => {
|
|
||||||
const totalSize = fileSizes.reduce((acc, size) => acc + size, 0);
|
|
||||||
const uploadTasks: WechatMiniprogram.UploadTask[] = [];
|
|
||||||
let uploadedSize = 0;
|
|
||||||
let lastUploadedSize = 0;
|
|
||||||
|
|
||||||
|
// 使用 Network.uploadFiles 上传文件
|
||||||
|
try {
|
||||||
|
const tempFileIds = await Network.uploadFiles({
|
||||||
|
mediaList: files.map(file => ({
|
||||||
|
path: file.tempFilePath,
|
||||||
|
size: file.size
|
||||||
|
})),
|
||||||
|
onProgress: (progress) => {
|
||||||
|
that.setData({
|
||||||
|
uploaded: IOSize.formatWithoutUnit(progress.uploaded, 2, Unit.MB),
|
||||||
|
uploadTotal: IOSize.format(progress.total, 2, Unit.MB),
|
||||||
|
uploadSpeed: `${IOSize.format(progress.speed)} / s`,
|
||||||
|
uploadProgress: progress.percent
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showLoading: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 上传完成转附件
|
||||||
|
const list = await MomentApi.create(tempFileIds);
|
||||||
|
wx.showToast({ title: "上传成功", icon: "success" });
|
||||||
|
const added = list.map((item: any) => {
|
||||||
|
const ext = JSON.parse(item.ext) as MediaAttachExt;
|
||||||
|
const thumbURL = `${config.url}/attachment/read/${item.mongoId}`;
|
||||||
|
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
type: ext.isImage ? MediaItemType.IMAGE : MediaItemType.VIDEO,
|
||||||
|
thumbURL,
|
||||||
|
sourceURL,
|
||||||
|
checked: false
|
||||||
|
} as Item;
|
||||||
|
});
|
||||||
|
// 前插列表
|
||||||
|
that.data.list.unshift(...added);
|
||||||
that.setData({
|
that.setData({
|
||||||
uploadTotal: IOSize.format(totalSize, 2, Unit.MB)
|
list: that.data.list,
|
||||||
|
isUploading: false,
|
||||||
|
uploaded: "0",
|
||||||
|
uploadTotal: "0 MB",
|
||||||
|
uploadProgress: 0
|
||||||
});
|
});
|
||||||
|
that.updateHasChecked();
|
||||||
// 计算上传速度
|
} catch (error) {
|
||||||
const speedUpdateInterval = setInterval(() => {
|
handleFail(error);
|
||||||
const chunkSize = uploadedSize - lastUploadedSize;
|
}
|
||||||
that.setData({
|
|
||||||
uploadSpeed: `${IOSize.format(chunkSize)} / s`
|
|
||||||
});
|
|
||||||
lastUploadedSize = uploadedSize;
|
|
||||||
}, 1000);
|
|
||||||
// 上传文件
|
|
||||||
const uploadPromises = files.map(file => {
|
|
||||||
return new Promise<string>((uploadResolve, uploadReject) => {
|
|
||||||
const task = wx.uploadFile({
|
|
||||||
url: `${config.url}/temp/file/upload`,
|
|
||||||
filePath: file.tempFilePath,
|
|
||||||
name: "file",
|
|
||||||
success: (resp) => {
|
|
||||||
const result = JSON.parse(resp.data);
|
|
||||||
if (result && result.code === 20000) {
|
|
||||||
// 更新进度
|
|
||||||
const progress = totalSize > 0 ? uploadedSize / totalSize : 1;
|
|
||||||
that.setData({
|
|
||||||
uploadProgress: Math.round(progress * 10000) / 100
|
|
||||||
});
|
|
||||||
uploadResolve(result.data[0].id);
|
|
||||||
} else {
|
|
||||||
uploadReject(new Error(`文件上传失败: ${result?.message || "未知错误"}`));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: (err) => uploadReject(new Error(`文件上传失败: ${err.errMsg}`))
|
|
||||||
});
|
|
||||||
// 监听上传进度事件
|
|
||||||
let prevProgress = 0;
|
|
||||||
task.onProgressUpdate((res) => {
|
|
||||||
const fileUploaded = (res.totalBytesExpectedToSend * res.progress) / 100;
|
|
||||||
const delta = fileUploaded - prevProgress;
|
|
||||||
uploadedSize += delta;
|
|
||||||
// 保存当前进度
|
|
||||||
prevProgress = fileUploaded;
|
|
||||||
// 更新进度条
|
|
||||||
that.setData({
|
|
||||||
uploaded: IOSize.formatWithoutUnit(uploadedSize, 2, Unit.MB),
|
|
||||||
uploadProgress: Math.round((uploadedSize / totalSize) * 10000) / 100
|
|
||||||
});
|
|
||||||
});
|
|
||||||
uploadTasks.push(task);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Promise.all(uploadPromises).then((tempFileIds) => {
|
|
||||||
wx.showLoading({
|
|
||||||
title: "正在保存..",
|
|
||||||
mask: true
|
|
||||||
})
|
|
||||||
// 清除定时器
|
|
||||||
clearInterval(speedUpdateInterval);
|
|
||||||
uploadTasks.forEach(task => task.offProgressUpdate());
|
|
||||||
that.setData({
|
|
||||||
uploadProgress: 100,
|
|
||||||
uploadSpeed: "0 MB / s"
|
|
||||||
});
|
|
||||||
// 上传完成转附件
|
|
||||||
wx.request({
|
|
||||||
url: `${config.url}/journal/moment/create`,
|
|
||||||
method: "POST",
|
|
||||||
header: {
|
|
||||||
Key: wx.getStorageSync("key")
|
|
||||||
},
|
|
||||||
data: tempFileIds,
|
|
||||||
success: async (resp: any) => {
|
|
||||||
wx.showToast({ title: "上传成功", icon: "success" });
|
|
||||||
const list = resp.data.data;
|
|
||||||
const added = list.map((item: any) => {
|
|
||||||
const ext = JSON.parse(item.ext) as MediaAttachExt;
|
|
||||||
const thumbURL = `${config.url}/attachment/read/${item.mongoId}`;
|
|
||||||
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
|
||||||
return {
|
|
||||||
id: item.id,
|
|
||||||
type: ext.isImage ? MediaItemType.IMAGE : MediaItemType.VIDEO,
|
|
||||||
thumbURL,
|
|
||||||
sourceURL,
|
|
||||||
checked: false
|
|
||||||
} as Item;
|
|
||||||
});
|
|
||||||
// 前插列表
|
|
||||||
that.data.list.unshift(...added);
|
|
||||||
that.setData({
|
|
||||||
list: that.data.list,
|
|
||||||
isUploading: false,
|
|
||||||
uploaded: "0",
|
|
||||||
uploadTotal: "0 MB",
|
|
||||||
uploadProgress: 0
|
|
||||||
});
|
|
||||||
that.updateHasChecked();
|
|
||||||
wx.hideLoading();
|
|
||||||
},
|
|
||||||
fail: handleFail
|
|
||||||
});
|
|
||||||
}).catch((e: Error) => {
|
|
||||||
// 取消所有上传任务
|
|
||||||
uploadTasks.forEach(task => task.abort());
|
|
||||||
that.updateHasChecked();
|
|
||||||
handleFail(e);
|
|
||||||
});
|
|
||||||
}).catch(handleFail);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -450,27 +358,14 @@ Page({
|
|||||||
})
|
})
|
||||||
const openId = await new Promise<string>((resolve, reject) => {
|
const openId = await new Promise<string>((resolve, reject) => {
|
||||||
wx.login({
|
wx.login({
|
||||||
success: (res) => {
|
success: async (res) => {
|
||||||
if (res.code) {
|
if (res.code) {
|
||||||
wx.request({
|
try {
|
||||||
url: `${config.url}/journal/openid`,
|
const openId = await JournalApi.getOpenId(res.code);
|
||||||
method: "POST",
|
resolve(openId);
|
||||||
header: {
|
} catch (error) {
|
||||||
Key: wx.getStorageSync("key")
|
reject(new Error("获取 openId 失败"));
|
||||||
},
|
}
|
||||||
data: {
|
|
||||||
code: res.code
|
|
||||||
},
|
|
||||||
success: (resp) => {
|
|
||||||
const data = resp.data as any;
|
|
||||||
if (data.code === 20000) {
|
|
||||||
resolve(data.data);
|
|
||||||
} else {
|
|
||||||
reject(new Error("获取 openId 失败"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: () => reject(new Error("获取 openId 请求失败"))
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
reject(new Error("获取登录凭证失败"));
|
reject(new Error("获取登录凭证失败"));
|
||||||
}
|
}
|
||||||
@ -491,36 +386,23 @@ Page({
|
|||||||
if (this.data.selectedJournalId) {
|
if (this.data.selectedJournalId) {
|
||||||
archiveData.id = this.data.selectedJournalId;
|
archiveData.id = this.data.selectedJournalId;
|
||||||
}
|
}
|
||||||
wx.request({
|
try {
|
||||||
url: `${config.url}/journal/moment/archive`,
|
await MomentApi.archive(archiveData);
|
||||||
method: "POST",
|
Events.emit("JOURNAL_REFRESH");
|
||||||
header: {
|
wx.showToast({ title: "归档成功", icon: "success" });
|
||||||
Key: wx.getStorageSync("key")
|
this.setData({
|
||||||
},
|
idea: "",
|
||||||
data: archiveData,
|
list: [],
|
||||||
success: async (resp: any) => {
|
hasChecked: false,
|
||||||
if (resp.data && resp.data.code === 20000) {
|
isArchiving: false,
|
||||||
Events.emit("JOURNAL_REFRESH");
|
selectedJournalId: undefined,
|
||||||
wx.showToast({ title: "归档成功", icon: "success" });
|
isVisibleArchivePopup: false
|
||||||
this.setData({
|
});
|
||||||
idea: "",
|
await Toolkit.sleep(1000);
|
||||||
list: [],
|
this.fetch();
|
||||||
hasChecked: false,
|
} catch (error) {
|
||||||
isArchiving: false,
|
handleFail();
|
||||||
selectedJournalId: undefined,
|
}
|
||||||
isVisibleArchivePopup: false
|
|
||||||
});
|
|
||||||
await Toolkit.sleep(1000);
|
|
||||||
this.fetch();
|
|
||||||
} else {
|
|
||||||
wx.showToast({ title: "归档失败", icon: "error" });
|
|
||||||
this.setData({
|
|
||||||
isArchiving: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: handleFail
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
allChecked() {
|
allChecked() {
|
||||||
this.data.list.forEach(item => item.checked = true);
|
this.data.list.forEach(item => item.checked = true);
|
||||||
@ -556,27 +438,21 @@ Page({
|
|||||||
confirmText: "删除已选",
|
confirmText: "删除已选",
|
||||||
confirmColor: "#E64340",
|
confirmColor: "#E64340",
|
||||||
cancelText: "取消",
|
cancelText: "取消",
|
||||||
success: res => {
|
success: async (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
const selected = this.data.list.filter(item => item.checked);
|
const selected = this.data.list.filter(item => item.checked);
|
||||||
wx.request({
|
try {
|
||||||
url: `${config.url}/journal/moment/delete`,
|
await MomentApi.delete(selected.map(item => item.id));
|
||||||
method: "POST",
|
wx.showToast({ title: "删除成功", icon: "success" });
|
||||||
header: {
|
const list = this.data.list.filter(item => !item.checked);
|
||||||
Key: wx.getStorageSync("key")
|
this.setData({
|
||||||
},
|
list
|
||||||
data: selected.map(item => item.id),
|
});
|
||||||
success: async (resp: any) => {
|
this.updateHasChecked();
|
||||||
if (resp.data && resp.data.code === 20000) {
|
} catch (error) {
|
||||||
wx.showToast({ title: "删除成功", icon: "success" });
|
console.error("删除 moment 失败:", error);
|
||||||
const list = this.data.list.filter(item => !item.checked);
|
wx.showToast({ title: "删除失败", icon: "error" });
|
||||||
this.setData({
|
}
|
||||||
list
|
|
||||||
});
|
|
||||||
this.updateHasChecked();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,9 +5,10 @@ import config from "../../../config/index"
|
|||||||
import Events from "../../../utils/Events";
|
import Events from "../../../utils/Events";
|
||||||
import Toolkit from "../../../utils/Toolkit";
|
import Toolkit from "../../../utils/Toolkit";
|
||||||
import { Journal, JournalPage, JournalPageType } from "../../../types/Journal";
|
import { Journal, JournalPage, JournalPageType } from "../../../types/Journal";
|
||||||
import { OrderType, QueryPageResult } from "../../../types/Model";
|
import { OrderType, } from "../../../types/Model";
|
||||||
import { ImageMetadata, MediaAttachExt } from "../../../types/Attachment";
|
import { ImageMetadata, MediaAttachExt } from "../../../types/Attachment";
|
||||||
import { MediaItem, MediaItemType } from "../../../types/UI";
|
import { MediaItem, MediaItemType } from "../../../types/UI";
|
||||||
|
import { JournalApi } from "../../../api/JournalApi";
|
||||||
|
|
||||||
interface IPortfolioData {
|
interface IPortfolioData {
|
||||||
page: JournalPage;
|
page: JournalPage;
|
||||||
@ -72,79 +73,71 @@ Page({
|
|||||||
this.setData({ stickyOffset: height });
|
this.setData({ stickyOffset: height });
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
fetch() {
|
async fetch() {
|
||||||
if (this.data.isFetching || this.data.isFinished) {
|
if (this.data.isFetching || this.data.isFinished) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setData({
|
this.setData({
|
||||||
isFetching: true
|
isFetching: true
|
||||||
});
|
});
|
||||||
wx.request({
|
try {
|
||||||
url: `${config.url}/journal/list`,
|
const pageResult = await JournalApi.getList(this.data.page);
|
||||||
method: "POST",
|
const list = pageResult.list;
|
||||||
header: {
|
if (!list || list.length === 0) {
|
||||||
Key: wx.getStorageSync("key")
|
|
||||||
},
|
|
||||||
data: this.data.page,
|
|
||||||
success: async (resp: any) => {
|
|
||||||
const pageResult = resp.data.data as QueryPageResult<Journal>;
|
|
||||||
const list = pageResult.list;
|
|
||||||
if (!list || list.length === 0) {
|
|
||||||
this.setData({
|
|
||||||
isFinished: true
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
list.forEach(journal => {
|
|
||||||
const mediaItems = journal.items!.filter((item) => item.attachType === "THUMB").map((thumbItem, index) => {
|
|
||||||
const metadata = thumbItem.metadata as ImageMetadata;
|
|
||||||
const ext = thumbItem.ext = JSON.parse(thumbItem.ext!.toString()) as MediaAttachExt;
|
|
||||||
const thumbURL = `${config.url}/attachment/read/${thumbItem.mongoId}`;
|
|
||||||
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
|
||||||
return {
|
|
||||||
type: ext.isVideo ? MediaItemType.VIDEO : MediaItemType.IMAGE,
|
|
||||||
thumbURL,
|
|
||||||
sourceURL,
|
|
||||||
size: thumbItem.size || 0,
|
|
||||||
attachmentId: thumbItem.id,
|
|
||||||
width: metadata.width,
|
|
||||||
height: metadata.height,
|
|
||||||
originalIndex: index
|
|
||||||
} as MediaItem;
|
|
||||||
});
|
|
||||||
journal.date = Time.toDate(journal.createdAt);
|
|
||||||
journal.time = Time.toTime(journal.createdAt);
|
|
||||||
journal.datetime = Time.toPassedDateTime(journal.createdAt);
|
|
||||||
journal.mediaItems = mediaItems;
|
|
||||||
journal.columnedItems = Toolkit.splitItemsIntoColumns(mediaItems, 3, (item) => {
|
|
||||||
if (item.width && item.height && 0 < item.width) {
|
|
||||||
return item.height / item.width;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
})
|
|
||||||
})
|
|
||||||
this.setData({
|
|
||||||
page: {
|
|
||||||
index: this.data.page.index + 1,
|
|
||||||
size: 8,
|
|
||||||
type: JournalPageType.NORMAL,
|
|
||||||
equalsExample: {
|
|
||||||
type: "PORTFOLIO"
|
|
||||||
},
|
|
||||||
orderMap: {
|
|
||||||
createdAt: OrderType.DESC
|
|
||||||
}
|
|
||||||
},
|
|
||||||
list: this.data.list.concat(list),
|
|
||||||
isFinished: list.length < this.data.page.size
|
|
||||||
});
|
|
||||||
},
|
|
||||||
complete: () => {
|
|
||||||
this.setData({
|
this.setData({
|
||||||
|
isFinished: true,
|
||||||
isFetching: false
|
isFetching: false
|
||||||
});
|
})
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
list.forEach(journal => {
|
||||||
|
const mediaItems = journal.items!.filter((item) => item.attachType === "THUMB").map((thumbItem, index) => {
|
||||||
|
const metadata = thumbItem.metadata as ImageMetadata;
|
||||||
|
const ext = thumbItem.ext = JSON.parse(thumbItem.ext!.toString()) as MediaAttachExt;
|
||||||
|
const thumbURL = `${config.url}/attachment/read/${thumbItem.mongoId}`;
|
||||||
|
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
||||||
|
return {
|
||||||
|
type: ext.isVideo ? MediaItemType.VIDEO : MediaItemType.IMAGE,
|
||||||
|
thumbURL,
|
||||||
|
sourceURL,
|
||||||
|
size: thumbItem.size || 0,
|
||||||
|
attachmentId: thumbItem.id,
|
||||||
|
width: metadata.width,
|
||||||
|
height: metadata.height,
|
||||||
|
originalIndex: index
|
||||||
|
} as MediaItem;
|
||||||
|
});
|
||||||
|
journal.date = Time.toDate(journal.createdAt);
|
||||||
|
journal.time = Time.toTime(journal.createdAt);
|
||||||
|
journal.datetime = Time.toPassedDateTime(journal.createdAt);
|
||||||
|
journal.mediaItems = mediaItems;
|
||||||
|
journal.columnedItems = Toolkit.splitItemsIntoColumns(mediaItems, 3, (item) => {
|
||||||
|
if (item.width && item.height && 0 < item.width) {
|
||||||
|
return item.height / item.width;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.setData({
|
||||||
|
page: {
|
||||||
|
index: this.data.page.index + 1,
|
||||||
|
size: 8,
|
||||||
|
type: JournalPageType.NORMAL,
|
||||||
|
equalsExample: {
|
||||||
|
type: "PORTFOLIO"
|
||||||
|
},
|
||||||
|
orderMap: {
|
||||||
|
createdAt: OrderType.DESC
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list: this.data.list.concat(list),
|
||||||
|
isFinished: list.length < this.data.page.size,
|
||||||
|
isFetching: false
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载 portfolio 列表失败:", error);
|
||||||
|
this.setData({ isFetching: false });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
preview(e: WechatMiniprogram.BaseEvent) {
|
preview(e: WechatMiniprogram.BaseEvent) {
|
||||||
const { journalIndex, itemIndex } = e.currentTarget.dataset;
|
const { journalIndex, itemIndex } = e.currentTarget.dataset;
|
||||||
|
|||||||
@ -198,7 +198,7 @@ Page({
|
|||||||
|
|
||||||
const sources = location.mediaItems.map(item => ({
|
const sources = location.mediaItems.map(item => ({
|
||||||
url: item.sourceURL,
|
url: item.sourceURL,
|
||||||
type: MediaItemType[item.type].toLowerCase()
|
type: item.type
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const total = sources.length;
|
const total = sources.length;
|
||||||
|
|||||||
Reference in New Issue
Block a user