思源数据库提交表单

对于思源数据库添加数据要从最后点击进行添加,感觉有点麻烦,用过飞书表格之后他有一个提交表单,特别方便,然后想移植到思源笔记上,现在终于实现了。

使用了思源官方挂件“按钮”。

首先,介绍一下我的表单设置

<div class="protyle-wysiwyg protyle-wysiwyg--attr" spellcheck="false" contenteditable="true" style="padding: 16px 96px 272px;" data-doc-type="NodeDocument" data-realwidth="585" data-readonly="false"><div data-subtype="h3" data-node-id="20250911135114-pu4ctnh" data-node-index="0" data-type="NodeHeading" class="h3" updated="20250912104425"><div contenteditable="true" spellcheck="false">主键:</div><div class="protyle-attr" contenteditable="false"></div></div><div data-node-id="20250912102432-2cfi7ug" data-node-index="1" data-type="NodeCodeBlock" class="code-block" updated="20250912104425"><div class="protyle-action"><span class="protyle-action--first protyle-action__language" contenteditable="false">主键</span><span class="fn__flex-1"></span><span class="b3-tooltips__nw b3-tooltips protyle-icon protyle-icon--first protyle-action__copy" aria-label="复制"><svg><use xlink:href="#iconCopy"></use></svg></span><span class="b3-tooltips__nw b3-tooltips protyle-icon protyle-icon--last protyle-action__menu" aria-label="更多"><svg><use xlink:href="#iconMore"></use></svg></span></div><div class="hljs" data-render="true" style="display: block;"><div class="fn__none"></div><div contenteditable="true" style="flex: 1 1 0%; white-space: pre; word-break: initial; font-variant-ligatures: none;" spellcheck="false">
</div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-subtype="h3" data-node-id="20250911135319-05ej2ad" data-node-index="2" data-type="NodeHeading" class="h3" updated="20250912103703"><div contenteditable="true" spellcheck="false">日期(XXXX-XX-XX,不填默认当前日期):</div><div class="protyle-attr" contenteditable="false"></div></div><div data-node-id="20250911135336-d7ypbzv" data-node-index="1" data-type="NodeCodeBlock" class="code-block" updated="20250912103703"><div class="protyle-action"><span class="protyle-action--first protyle-action__language" contenteditable="false">日期</span><span class="fn__flex-1"></span><span class="b3-tooltips__nw b3-tooltips protyle-icon protyle-icon--first protyle-action__copy" aria-label="复制"><svg><use xlink:href="#iconCopy"></use></svg></span><span class="b3-tooltips__nw b3-tooltips protyle-icon protyle-icon--last protyle-action__menu" aria-label="更多"><svg><use xlink:href="#iconMore"></use></svg></span></div><div class="hljs" data-render="true" style="display: block;"><div class="fn__none"></div><div contenteditable="true" style="flex: 1 1 0%; white-space: pre; word-break: initial; font-variant-ligatures: none;" spellcheck="false">
</div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-subtype="h3" data-node-id="20250911135353-qilr4h3" data-node-index="4" data-type="NodeHeading" class="h3" updated="20250912104427"><div contenteditable="true" spellcheck="false">单选:</div><div class="protyle-attr" contenteditable="false"></div></div><div data-node-id="20250911135439-cs5xi8a" data-node-index="5" data-type="NodeBlockquote" class="bq" updated="20250912104427"><div data-subtype="t" data-node-id="20250911135458-t7dgs5w" data-type="NodeList" class="list" updated="20250912104427"><div data-marker="*" data-subtype="t" data-node-id="20250911135501-bbm5ua3" data-node-index="1" data-type="NodeListItem" class="li" updated="20250912104806"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div><div data-node-id="20250912104806-lr8bidl" data-type="NodeParagraph" class="p" updated="20250912104806"><div contenteditable="true" spellcheck="false">个人吃饭</div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-marker="*" data-subtype="t" data-node-id="20250911135510-d0xgae5" data-type="NodeListItem" class="li" updated="20250911171204"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div><div data-node-id="20250911135510-za6k2zo" data-type="NodeParagraph" class="p" updated="20250911135516"><div contenteditable="true" spellcheck="false">多人聚餐</div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-marker="*" data-subtype="t" data-node-id="20250911135516-1hgh62z" data-type="NodeListItem" class="li" updated="20250912104153"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div><div data-node-id="20250912104153-krt0l0r" data-type="NodeParagraph" class="p" updated="20250912104153"><div contenteditable="true" spellcheck="false">网络购物</div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-marker="*" data-subtype="t" data-node-id="20250911135521-2pyfuc2" data-type="NodeListItem" class="li" updated="20250912104153"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div><div data-node-id="20250912104153-paioqwv" data-type="NodeParagraph" class="p" updated="20250912104153"><div contenteditable="true" spellcheck="false">红包转账</div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-marker="*" data-subtype="t" data-node-id="20250911135527-9ay8kpp" data-type="NodeListItem" class="li" updated="20250912103623"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div><div data-node-id="20250912103623-8mv6r76" data-type="NodeParagraph" class="p" updated="20250912103623"><div contenteditable="true" spellcheck="false">交通住宿</div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-marker="*" data-subtype="t" data-node-id="20250911135531-aozy2nu" data-type="NodeListItem" class="li" updated="20250912103623"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div><div data-node-id="20250912103623-2msvvym" data-type="NodeParagraph" class="p" updated="20250912103623"><div contenteditable="true" spellcheck="false">出行旅游</div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-marker="*" data-subtype="t" data-node-id="20250911135535-fz9deav" data-type="NodeListItem" class="li" updated="20250912095426"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div><div data-node-id="20250911135535-4iooegx" data-type="NodeParagraph" class="p" updated="20250911135540"><div contenteditable="true" spellcheck="false">虚拟充值</div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-marker="*" data-subtype="t" data-node-id="20250911135540-28t6uqx" data-type="NodeListItem" class="li" updated="20250912103528"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div><div data-node-id="20250912103528-qny0poa" data-type="NodeParagraph" class="p" updated="20250912103528"><div contenteditable="true" spellcheck="false">其他</div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-subtype="h3" data-node-id="20250911135626-baosp0c" data-node-index="6" data-type="NodeHeading" class="h3" updated="20250912104428"><div contenteditable="true" spellcheck="false">数字:</div><div class="protyle-attr" contenteditable="false"></div></div><div data-node-id="20250911135647-qx73tr9" data-node-index="1" data-type="NodeCodeBlock" class="code-block" updated="20250912104428"><div class="protyle-action"><span class="protyle-action--first protyle-action__language" contenteditable="false">数字</span><span class="fn__flex-1"></span><span class="b3-tooltips__nw b3-tooltips protyle-icon protyle-icon--first protyle-action__copy" aria-label="复制"><svg><use xlink:href="#iconCopy"></use></svg></span><span class="b3-tooltips__nw b3-tooltips protyle-icon protyle-icon--last protyle-action__menu" aria-label="更多"><svg><use xlink:href="#iconMore"></use></svg></span></div><div class="hljs" data-render="true" style="display: block;"><div class="fn__none"></div><div contenteditable="true" style="flex: 1 1 0%; white-space: pre; word-break: initial; font-variant-ligatures: none;" spellcheck="false">
</div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-subtype="h3" data-node-id="20250911135632-p0gdr5c" data-node-index="8" data-type="NodeHeading" class="h3" updated="20250912104536"><div contenteditable="true" spellcheck="false">返现:</div><div class="protyle-attr" contenteditable="false"></div></div><div data-node-id="20250911135702-h56lxky" data-node-index="1" data-type="NodeCodeBlock" class="code-block" updated="20250912104429"><div class="protyle-action"><span class="protyle-action--first protyle-action__language" contenteditable="false">返现</span><span class="fn__flex-1"></span><span class="b3-tooltips__nw b3-tooltips protyle-icon protyle-icon--first protyle-action__copy" aria-label="复制"><svg><use xlink:href="#iconCopy"></use></svg></span><span class="b3-tooltips__nw b3-tooltips protyle-icon protyle-icon--last protyle-action__menu" aria-label="更多"><svg><use xlink:href="#iconMore"></use></svg></span></div><div class="hljs" data-render="true" style="display: block;"><div class="fn__none"></div><div contenteditable="true" style="flex: 1 1 0%; white-space: pre; word-break: initial; font-variant-ligatures: none;" spellcheck="false">
</div></div><div class="protyle-attr" contenteditable="false"></div></div><div data-node-id="20250912104536-rt5i7pd" data-node-index="10" data-type="NodeWidget" class="iframe" updated="20250912104536" data-subtype="widget"><div class="iframe-content"><iframe src="/widgets/Button/" data-subtype="widget" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="width: 109px; height: 65px;"></iframe><span class="protyle-action__drag" contenteditable="false"></span></div><div class="protyle-attr" contenteditable="false"></div></div><div data-node-id="20250912104805-3q8gseu" data-type="NodeParagraph" class="p"><div contenteditable="true" spellcheck="false"></div><div class="protyle-attr" contenteditable="false"></div></div></div>

大概是这样子的

file 消费表单.png

然后我的数据库设置是

image.png

表单和数据库的位置关系应该没有影响,但是我把数据库放在了表单的子文档

image.png

这样每次填写完消费记录点击按钮,的时候执行代码,做到提交信息到数据库,然后并清除表单块的信息,方便下次填写。

运行结果

image.png

image.png

代码如下

// 编辑return修改按钮名称
function getButtonName() {
    return "提交"; // 按钮显示文字
}

// 按钮按下时执行
function executeScriptFunctions() {

    const token = "jpotli7es6bkshts";

    // 需要清空内容的代码块(就是你设置的填写数据的块,取决于你有多少个要填写的项)
    const codeBlocks = [
        "99999999999999-aaaaaaa",
        "99999999999999-aaaaaaa",
        "99999999999999-aaaaaaa",
        "99999999999999-aaaaaaa"
    ];

    // 单选列表块(取消勾选,这个是单选列表,单独摘出来处理)
    const listBlockId = "99999999999999-aaaaaaa";

    // ------------------ 工具函数 ------------------
    function normalizeDateStr(dateStr) {
        if (!dateStr || dateStr.trim() === "") return null;
        const match = dateStr.trim().match(/^(\d{4})[-/](\d{1,2})[-/](\d{1,2})$/);
        if (!match) return null;
        const year = match[1];
        const month = String(parseInt(match[2], 10)).padStart(2, '0');
        const day = String(parseInt(match[3], 10)).padStart(2, '0');
        return `${year}-${month}-${day}`;
    }

    function dateToTimestamp(dateStr) {
        if (!dateStr || dateStr.trim() === "") return new Date().getTime();
        const normalized = normalizeDateStr(dateStr);
        if (!normalized) return null;
        const [year, month, day] = normalized.split('-').map(Number);
        return new Date(year, month - 1, day, 12, 0, 0).getTime();
    }
    //读取文档内容
    async function getRawNoteContent(docId) {
        try {
            const res = await fetch("http://127.0.0.1:6806/api/filetree/getDoc", {
                method: "POST",
                headers: { "Content-Type": "application/json", "Authorization": `Token ${token}` },
                body: JSON.stringify({ id: docId, mode: 0 })
            });
            const data = await res.json();
            if (data.code !== 0) throw new Error(data.msg);
            return data.data.content;
        } catch (err) {
            console.error("获取原始笔记失败:", err.message);
            return null;
        }
    }

    function parseRawContent(rawHtml) {
        const parser = new DOMParser();
        const doc = parser.parseFromString(rawHtml, 'text/html');
        const result = {};
        const headings = doc.querySelectorAll('[data-type="NodeHeading"][data-subtype="h3"]');
        headings.forEach(heading => {
            const title = heading.querySelector('[contenteditable="true"]')?.textContent.trim() || "未知标题";
            const contentBlock = heading.nextElementSibling;
            if (!contentBlock) { result[title] = ""; return; }
            let content;
            const type = contentBlock.getAttribute('data-type');
            if (type === "NodeCodeBlock") {
                content = contentBlock.querySelector('[contenteditable="true"]')?.textContent.trim() || "";
            } else if (type === "NodeBlockquote") {
                const items = contentBlock.querySelectorAll('[data-type="NodeListItem"]');
                content = Array.from(items).map(item => ({
                    text: item.querySelector('[contenteditable="true"]')?.textContent.trim() || "未知选项",
                    isSelected: item.classList.contains('protyle-task--done')
                }));
            } else {
                content = contentBlock.textContent.trim() || "";
            }
            result[title] = content;
        });
        return result;
    }

    async function clearCodeBlock(blockId) {
        const res = await fetch("http://127.0.0.1:6806/api/block/getBlockDOM", {
            method: "POST",
            headers: { "Content-Type": "application/json", "Authorization": `Token ${token}` },
            body: JSON.stringify({ id: blockId })
        });
        const data = await res.json();
        if (data.code !== 0) { console.error("获取代码块失败:", blockId); return; }
        const parser = new DOMParser();
        const doc = parser.parseFromString(data.data.dom, "text/html");
        const editable = doc.querySelector('div.hljs > div[contenteditable="true"]');
        if (editable) editable.textContent = "";
        const updateRes = await fetch("http://127.0.0.1:6806/api/block/updateBlock", {
            method: "POST",
            headers: { "Content-Type": "application/json", "Authorization": `Token ${token}` },
            body: JSON.stringify({ id: blockId, data: doc.body.innerHTML, dataType: "dom" })
        });
        const result = await updateRes.json();
        if (result.code === 0) console.log(`✅ 清空代码块 ${blockId} 成功`);
    }

    async function uncheckListItems(listBlockId) {
        const res = await fetch("http://127.0.0.1:6806/api/block/getBlockDOM", {
            method: "POST",
            headers: { "Content-Type": "application/json", "Authorization": `Token ${token}` },
            body: JSON.stringify({ id: listBlockId })
        });
        const data = await res.json();
        if (data.code !== 0) return;
        const parser = new DOMParser();
        const doc = parser.parseFromString(data.data.dom, "text/html");
        const items = doc.querySelectorAll('[data-type="NodeListItem"].protyle-task--done');
        for (const item of items) {
            const text = item.querySelector('[contenteditable="true"]')?.textContent || "";
            await fetch("http://127.0.0.1:6806/api/block/updateBlock", {
                method: "POST",
                headers: { "Content-Type": "application/json", "Authorization": `Token ${token}` },
                body: JSON.stringify({ id: item.getAttribute("data-node-id"), data: `- [ ] ${text}`, dataType: "markdown" })
            });
        }
        console.log("✅ 已取消单选列表勾选项");
    }

    async function insertDataToDB(parsedData, avID) {
        const keysRes = await fetch("http://127.0.0.1:6806/api/av/getAttributeViewKeysByAvID", {
            method: "POST",
            headers: { "Content-Type": "application/json", "Authorization": `Token ${token}` },
            body: JSON.stringify({ avID })
        });
        const keysData = await keysRes.json();
        if (keysData.code !== 0) { console.error("获取列信息失败"); return; }
        const keyMap = {};
        keysData.data.forEach(col => keyMap[col.name] = { id: col.id, type: col.type });

        const radioOptions = parsedData["单选:"] || [];
        const selected = radioOptions.find(opt => opt.isSelected)?.text || "";

        const dateKey = Object.keys(parsedData).find(k => k.includes("日期")) || "";
        const dateTimestamp = dateToTimestamp(parsedData[dateKey] || "");

        const blocksValues = [[
            { keyID: keyMap["主键"].id, block: { content: parsedData["主键:"] || "" } },
            { keyID: keyMap["单选"].id, mSelect: selected ? [{ content: selected }] : [] },
            { keyID: keyMap["数字"].id, number: { content: Number(parsedData["数字:"] || 0), isNotEmpty: !!parsedData["数字:"] } },
            { keyID: keyMap["日期"].id, date: { content: dateTimestamp, isNotEmpty: true } },
            { keyID: keyMap["返现"].id, number: { content: Number(parsedData["返现:"] || 0), isNotEmpty: !!parsedData["返现:"] } }
        ]];

        const res = await fetch("http://127.0.0.1:6806/api/av/appendAttributeViewDetachedBlocksWithValues", {
            method: "POST",
            headers: { "Content-Type": "application/json", "Authorization": `Token ${token}` },
            body: JSON.stringify({ avID, blocksValues })
        });
        const result = await res.json();
        if (result.code === 0) {
            console.log("✅ 数据插入成功!");

            // 数据插入成功后再清空代码块并取消勾选
            for (const id of codeBlocks) await clearCodeBlock(id);
            await uncheckListItems(listBlockId);

            alert("提交成功!");
        } else {
            console.error("❌ 数据插入失败", result);
        }
    }

    // ------------------ 主流程 ------------------
    // docId是你的表单的文档ID,acID是你的消费数据库id(不是块id)
    (async () => {
        const docId = "99999999999999-aaaaaaa";
        const avID = "99999999999999-aaaaaaa";

        const rawHtml = await getRawNoteContent(docId);
        if (!rawHtml) return;

        const parsedData = parseRawContent(rawHtml);
        console.log("解析后的数据:", parsedData);

        await insertDataToDB(parsedData, avID);
    })();
}

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    28448 引用 • 119791 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    99 引用 • 367 回帖 • 1 关注
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 707 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 563 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    5 引用 • 16 回帖 • 3 关注
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    2 引用 • 14 回帖 • 6 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    14 引用 • 84 回帖 • 1 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 91 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 641 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    194 引用 • 1034 回帖
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    8 引用 • 69 回帖 • 6 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 11 关注
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 121 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    97 引用 • 155 回帖
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 193 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    561 引用 • 677 回帖
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 8 关注
  • OnlyOffice
    4 引用 • 41 关注
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    176 引用 • 544 回帖
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有机会重制。

    14 引用 • 258 回帖
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    15 引用 • 7 回帖
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    232 引用 • 484 回帖
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 74 关注
  • Excel
    32 引用 • 29 回帖 • 1 关注
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    85 引用 • 414 回帖
  • 音乐

    你听到信仰的声音了么?

    63 引用 • 513 回帖