mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-17 15:10:12 +01:00
Optimize attributeView image browsing (#14843)
This commit is contained in:
parent
b06cee76f8
commit
2b03a364af
7 changed files with 169 additions and 8 deletions
|
|
@ -92,3 +92,60 @@ export const previewDocImage = (src: string, id: string) => {
|
|||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const previewAttrViewImages = (src: string, avID: string,viewID: string,query?:string,pageSize?: number) => {
|
||||
addScript(`${Constants.PROTYLE_CDN}/js/viewerjs/viewer.js?v=1.11.7`, "protyleViewerScript").then(() => {
|
||||
fetchPost("/api/av/getCurrentAttrViewImages", {
|
||||
id: avID,
|
||||
query: query,
|
||||
pageSize: pageSize,
|
||||
viewID: viewID
|
||||
}, (response) => {
|
||||
const imagesElement = document.createElement("ul");
|
||||
let html = "";
|
||||
let initialViewIndex = -1;
|
||||
response.data.forEach((item: string, index: number) => {
|
||||
if (item) {
|
||||
html += `<li><img src="${item}"></li>`;
|
||||
if (initialViewIndex === -1 && (src.endsWith(encodeURI(item)) || src.endsWith(item))) {
|
||||
initialViewIndex = index;
|
||||
}
|
||||
}
|
||||
});
|
||||
imagesElement.innerHTML = html;
|
||||
window.siyuan.viewer = new Viewer(imagesElement, {
|
||||
title: [1, (image: HTMLImageElement, imageData: IObject) => {
|
||||
let name = image.alt;
|
||||
if (!name) {
|
||||
name = image.src.substring(image.src.lastIndexOf("/") + 1);
|
||||
}
|
||||
name = name.substring(0, name.lastIndexOf(".")).replace(/-\d{14}-\w{7}$/, "");
|
||||
return `${name} [${imageData.naturalWidth} × ${imageData.naturalHeight}]`;
|
||||
}],
|
||||
button: false,
|
||||
initialViewIndex,
|
||||
transition: false,
|
||||
hidden: function () {
|
||||
window.siyuan.viewer.destroy();
|
||||
},
|
||||
toolbar: {
|
||||
zoomIn: true,
|
||||
zoomOut: true,
|
||||
oneToOne: true,
|
||||
reset: true,
|
||||
prev: true,
|
||||
play: true,
|
||||
next: true,
|
||||
rotateLeft: true,
|
||||
rotateRight: true,
|
||||
flipHorizontal: true,
|
||||
flipVertical: true,
|
||||
close: function () {
|
||||
window.siyuan.viewer.destroy();
|
||||
},
|
||||
},
|
||||
});
|
||||
window.siyuan.viewer.show();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import {openMenuPanel} from "./openMenuPanel";
|
|||
import {hintRef} from "../../hint/extend";
|
||||
import {focusBlock, focusByRange} from "../../util/selection";
|
||||
import {showMessage} from "../../../dialog/message";
|
||||
import {previewImage} from "../../preview/image";
|
||||
import {previewAttrViewImages} from "../../preview/image";
|
||||
import {openEmojiPanel, unicode2Emoji} from "../../../emoji";
|
||||
import * as dayjs from "dayjs";
|
||||
import {openCalcMenu} from "./calc";
|
||||
|
|
@ -64,7 +64,13 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
|
|||
}
|
||||
const imgElement = hasClosestByClassName(event.target, "av__cellassetimg");
|
||||
if (imgElement) {
|
||||
previewImage((imgElement as HTMLImageElement).src);
|
||||
previewAttrViewImages(
|
||||
(imgElement as HTMLImageElement).src,
|
||||
blockElement.getAttribute("data-av-id"),
|
||||
blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW),
|
||||
(blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement)?.value.trim() || "",
|
||||
parseInt(blockElement.dataset.pageSize) || undefined
|
||||
);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {openMenu} from "../../../menus/commonMenuItem";
|
|||
import {MenuItem} from "../../../menus/Menu";
|
||||
import {copyPNGByLink, exportAsset} from "../../../menus/util";
|
||||
import {setPosition} from "../../../util/setPosition";
|
||||
import {previewImage} from "../../preview/image";
|
||||
import {previewAttrViewImages} from "../../preview/image";
|
||||
import {genAVValueHTML} from "./blockAttr";
|
||||
import {hideMessage, showMessage} from "../../../dialog/message";
|
||||
import {fetchPost} from "../../../util/fetch";
|
||||
|
|
@ -338,8 +338,13 @@ export const editAssetItem = (options: {
|
|||
icon: "iconPreview",
|
||||
label: window.siyuan.languages.cardPreview,
|
||||
click() {
|
||||
previewImage(linkAddress);
|
||||
}
|
||||
previewAttrViewImages(
|
||||
linkAddress,
|
||||
options.blockElement.getAttribute("data-av-id"),
|
||||
options.blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW),
|
||||
(options.blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement)?.value.trim() || "",
|
||||
parseInt(options.blockElement.getAttribute("data-page-size")) || undefined
|
||||
)}
|
||||
});
|
||||
}
|
||||
if (openSubMenu.length > 0) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import {getSearch} from "../../../util/functions";
|
|||
/// #if !MOBILE
|
||||
import {openAsset} from "../../../editor/util";
|
||||
/// #endif
|
||||
import {previewImage} from "../../preview/image";
|
||||
import {previewAttrViewImages} from "../../preview/image";
|
||||
import {assetMenu} from "../../../menus/protyle";
|
||||
import {addView, bindSwitcherEvent, bindViewEvent, getSwitcherHTML, getViewHTML, openViewMenu} from "./view";
|
||||
import {focusBlock} from "../../util/selection";
|
||||
|
|
@ -1259,13 +1259,22 @@ export const openMenuPanel = (options: {
|
|||
)) {
|
||||
openAsset(options.protyle.app, assetLink.trim(), parseInt(getSearch("page", assetLink)), "right");
|
||||
} else if (Constants.SIYUAN_ASSETS_IMAGE.includes(suffix)) {
|
||||
previewImage(assetLink);
|
||||
previewAttrViewImages(assetLink,avID,
|
||||
options.blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW),
|
||||
(options.blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement)?.value.trim() || "",
|
||||
parseInt(options.blockElement.getAttribute("data-page-size")) || undefined
|
||||
)
|
||||
|
||||
} else {
|
||||
window.open(assetLink);
|
||||
}
|
||||
/// #else
|
||||
if (Constants.SIYUAN_ASSETS_IMAGE.includes(suffix)) {
|
||||
previewImage(assetLink);
|
||||
previewAttrViewImages(assetLink,avID,
|
||||
options.blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW),
|
||||
(options.blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement)?.value.trim() || "",
|
||||
parseInt(options.blockElement.getAttribute("data-page-size")) || undefined
|
||||
)
|
||||
} else {
|
||||
window.open(assetLink);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -600,6 +600,49 @@ func renderAttributeView(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func getCurrentAttrViewImages(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
||||
arg, ok := util.JsonArg(c, ret)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
id := arg["id"].(string)
|
||||
viewIDArg := arg["viewID"]
|
||||
var viewID string
|
||||
if nil != viewIDArg {
|
||||
viewID = viewIDArg.(string)
|
||||
}
|
||||
page := 1
|
||||
pageArg := arg["page"]
|
||||
if nil != pageArg {
|
||||
page = int(pageArg.(float64))
|
||||
}
|
||||
|
||||
pageSize := -1
|
||||
pageSizeArg := arg["pageSize"]
|
||||
if nil != pageSizeArg {
|
||||
pageSize = int(pageSizeArg.(float64))
|
||||
}
|
||||
|
||||
query := ""
|
||||
queryArg := arg["query"]
|
||||
if nil != queryArg {
|
||||
query = queryArg.(string)
|
||||
}
|
||||
|
||||
images, err := model.GetCurrentAttributeViewImages(id, viewID, query, page, pageSize)
|
||||
if err != nil {
|
||||
ret.Code = -1
|
||||
ret.Msg = err.Error()
|
||||
return
|
||||
}
|
||||
ret.Data = images
|
||||
}
|
||||
|
||||
|
||||
func getAttributeViewKeys(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
|
|
|||
|
|
@ -452,6 +452,8 @@ func ServeAPI(ginServer *gin.Engine) {
|
|||
ginServer.Handle("POST", "/api/av/getAttributeViewKeysByAvID", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, getAttributeViewKeysByAvID)
|
||||
ginServer.Handle("POST", "/api/av/duplicateAttributeViewBlock", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, duplicateAttributeViewBlock)
|
||||
ginServer.Handle("POST", "/api/av/appendAttributeViewDetachedBlocksWithValues", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, appendAttributeViewDetachedBlocksWithValues)
|
||||
ginServer.Handle("POST", "/api/av/getCurrentAttrViewImages", model.CheckAuth, getCurrentAttrViewImages)
|
||||
|
||||
|
||||
ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, model.CheckAdminRole, chatGPT)
|
||||
ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, model.CheckAdminRole, chatGPTWithAction)
|
||||
|
|
|
|||
|
|
@ -933,6 +933,45 @@ func renderAttributeView(attrView *av.AttributeView, viewID, query string, page,
|
|||
return
|
||||
}
|
||||
|
||||
func GetCurrentAttributeViewImages(avID, viewID, query string, page, pageSize int) (ret []string, err error) {
|
||||
|
||||
var attrView *av.AttributeView
|
||||
attrView, err = av.ParseAttributeView(avID)
|
||||
if err != nil {
|
||||
logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
|
||||
return
|
||||
}
|
||||
var view *av.View
|
||||
|
||||
if "" != viewID {
|
||||
view, _ = attrView.GetCurrentView(viewID)
|
||||
} else {
|
||||
view = attrView.GetView(attrView.ViewID)
|
||||
}
|
||||
|
||||
table := sql.RenderAttributeViewTable(attrView, view, query)
|
||||
table.FilterRows(attrView)
|
||||
table.SortRows(attrView)
|
||||
|
||||
for _, row := range table.Rows {
|
||||
for _, cell := range row.Cells {
|
||||
if nil != cell.Value {
|
||||
if av.KeyTypeMAsset == cell.Value.Type {
|
||||
if nil != cell.Value.MAsset {
|
||||
for _, a := range cell.Value.MAsset {
|
||||
if av.AssetTypeImage == a.Type {
|
||||
ret = append(ret, a.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (tx *Transaction) doUnbindAttrViewBlock(operation *Operation) (ret *TxErr) {
|
||||
err := unbindAttributeViewBlock(operation, tx)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue