1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
| <template> <div class="imjoy noselect"> <!-- 整个imjoy页面框架是通过vue material这个组件库的md-app进行组织的 --> <!-- 它包括了md-app-toolbar工具栏、 md-app-drawer菜单栏和md-app-content内容区三部分 --> <!-- 相关教程见:https: <md-app> <!-- 工具栏就是最上面的横条,里面的内容直接全部删除了,仅保留架子 --> <md-app-toolbar class="md-dense app-toolbar" md-elevation="0"> </md-app-toolbar>
<!-- 接下来就是左侧的菜单栏 --> <!-- drawer的属性设置见:https: <!-- 具体地: --> <!-- (1)菜单栏是否可见是通过md-active属性控制,其通过v-bind绑定到了menuVisible这个变量上 --> <!-- (2)菜单栏关闭和打开两个事件都通过v-on绑定到了wm.resizeAll()函数上 --> <!-- (3)菜单栏是否常驻md-persistent和菜单栏是否支持触屏下的swipe绑定到了screenWidth这个变量上 --> <md-app-drawer :md-active.sync="menuVisible" @md-closed="wm.resizeAll()" @md-opened="wm.resizeAll()" :md-persistent="screenWidth > 800 ? 'full' : null" :md-swipeable="screenWidth > 600 ? false : true" > <!-- 接下来是将上传文件,添加工作流,添加插件和插件列表都放在了一个card中 --> <!-- 这个card的显示有两个判断语句,一个是用v-show判断plugin_loaded这个变量是否为true --> <!-- 另一个是用v-if判断pm这个变量是否为true, --> <!-- v-if和v-show看起来差不多,但有区别,见:https: <md-card id="plugin-menu" v-show="plugin_loaded" v-if="pm"> <!-- 将files,workflow和plugins都放在了card的header中, --> <!-- 这里我们将files和workflow都删掉了,仅留plugins的代码 --> <md-card-header> <!-- 添加plugins就是一个按钮,其class也是由v-bind绑定并判断 --> <!-- 该按钮的点击时间用v-on绑定到了showPluginManagement()函数上 --> <!-- 当点击该按钮后, 从而执行该函数,其中有一个非常重要的变量:--> <!-- this.showAddPluginDialog会设为true --> <!-- 从而会引发如下对话框的弹出: <md-dialog class="plugin-dialog" :md-active.sync="showAddPluginDialog" :md-click-outside-to-close="true" > --> <md-button ref="add_plugin_button" :class="pm.installed_plugins.length > 0 ? '' : 'md-primary'" @click="showPluginManagement()" > <md-icon>add</md-icon>Plugins </md-button> </md-card-header>
<!-- 接下来就是将插件列表放在card的content区域 --> <md-card-content> <!-- 使用v-for来循环插件列表,并对每一项提供了key的身份 --> <!-- v-for的教程见:https: <div v-for="plugin in sortedRunnablePlugins()" :key="plugin.name"> <!-- 增加一个分割线 --> <md-divider></md-divider> <div style="display: flex;"> <!-- 这里对每一个插件会包装一个badge徽章,用途是判断它需不需要升级 --> <!-- 如果需要升级,会出现一个NEW的角标 --> <md-badge :class="plugin.update_available ? '' : 'hide-badge'" class="md-square md-primary" md-dense md-content="NEW" > <!-- 这里是对插件的icon按钮点击后会出现的菜单进行定义 --> <md-menu md-size="medium"> <!-- 触发菜单的icon按钮定义 --> <md-button class="md-icon-button" :class="plugin.running ? 'md-accent' : ''" md-menu-trigger > <!-- 插件的加载状态 --> <md-progress-spinner v-if="plugin.initializing || plugin.terminating" class="md-accent" :md-diameter="20" md-mode="indeterminate" ></md-progress-spinner> <!-- icon会判断该插件有没有提供自定义的图标,如果没有,则使用默认的extension图标 --> <!-- 这个地方调用的就是之前入口文件所全局注册的PluginIcon组件 --> <plugin-icon v-else :icon="plugin.config.icon" ></plugin-icon> <!-- 按钮的工具提示信息 --> <md-tooltip v-if="screenWidth > 500">{{ plugin.name + ": " + plugin.config.description }}</md-tooltip> </md-button>
<!-- 点击icon按钮后弹出的菜单选项 --> <md-menu-content> <!-- Docs选项,绑定了showDoc方法 --> <md-menu-item @click="showDoc(plugin.id)"> <md-icon>description</md-icon>Docs </md-menu-item> <!-- Share选项,不一定会显示,有一个v-if条件渲染 --> <md-menu-item v-if="plugin.config.origin" @click="sharePlugin(plugin.id)" > <md-icon>share</md-icon>Share </md-menu-item> <!-- Export选项,绑定了downloadPlugin --> <md-menu-item @click="downloadPlugin(plugin.id)"> <md-icon>cloud_download</md-icon>Export </md-menu-item> <!-- Edit选项,绑定了editPlugin --> <md-menu-item @click="editPlugin(plugin.id)"> <md-icon>edit</md-icon>Edit </md-menu-item> <!-- Reload选项,绑定了reloadPlugin --> <md-menu-item @click="reloadPlugin(plugin.config)"> <md-icon>autorenew</md-icon>Reload </md-menu-item> <!-- Terminate选项,绑定了unloadPlugin --> <md-menu-item @click="unloadPlugin(plugin)"> <md-icon>clear</md-icon>Terminate </md-menu-item> <!-- Remove选项,绑定了removePlugin --> <md-menu-item class="md-accent" @click="removePlugin(plugin)" > <md-icon>delete_forever</md-icon>Remove </md-menu-item>
</md-menu-content> </md-menu> </md-badge>
<!-- 接下来就是由插件的名称所形成的按钮 --> <!-- 对于需要链接到engine的插件,还会检测其状态,如果没有链接到engine上,就会disable该按钮,从而无法运行. --> <!-- 对于鼠标操作,也附加了鼠标按钮修饰符,防止误操作,教程见:https: <!-- 点击该按钮后就会运行runOp方法 --> <md-button class="joy-run-button" :class=" plugin.running ? 'busy-plugin' : plugin._disconnected && plugin.engine ? 'md-accent' : 'md-primary' " :disabled="plugin._disconnected && !plugin.engine" @click.exact=" plugin._disconnected ? connectPlugin(plugin) : runOp(plugin.ops[plugin.name]) " @click.right.exact="logPlugin(plugin)" > {{ plugin.config.name + " " + plugin.config.badges }} </md-button>
</div>
<!-- 这个地方是ImJoy的核心!! --> <!-- 此处也是ImJoy的名称的来源,即ImJoy来自于joy.js这个库 --> <!-- 这个地方需要后面仔细研究机理 --> <div v-for="op in plugin.ops" :key="op.plugin_id + op.name" v-show="true" > <joy :config="op" :show="true"></joy> </div> <md-divider></md-divider> </div> <md-divider></md-divider> </md-card-content> </md-card> </md-app-drawer>
<!-- 接下来就是整个界面的第三部分,即内容区 --> <md-app-content :class="workspace_dropping ? 'file-dropping' : ''" class="whiteboard-content" > <!-- 就是引用了whiteboard这个组件 --> <whiteboard v-if="wm" id="whiteboard" @create="createWindow($event)" :mode="wm.window_mode" :window-manager="wm" ></whiteboard> </md-app-content>
<!-- 以上就是整个界面的布局 --> </md-app>
<!-- 这个是消息提醒对话框,当某处调用showAlert()函数时会触发,比如api.alert时--> <md-dialog-alert class="api-dialog" :md-active.sync="alert_config.show" :md-title="alert_config.title" :md-content="alert_config.content" :md-confirm-text="alert_config.confirm_text" />
<!-- 这个是消息确认对话框,当某处调用showConfirm()函数时会触发,比如删除插件时 --> <md-dialog-confirm class="api-dialog" :md-active.sync="confirm_config.show" :md-title="confirm_config.title" :md-content="confirm_config.content" :md-confirm-text="confirm_config.confirm_text" :md-cancel-text="confirm_config.canel_text" @md-confirm="confirm_config.confirm" @md-cancel="confirm_config.cancel" />
<!-- 前面已分析到,点击添加Plugins后会触发如下插件对话框的弹出 --> <md-dialog class="plugin-dialog" :md-active.sync="showAddPluginDialog" :md-click-outside-to-close="true" > <!-- 设置该对话框的标题 --> <md-dialog-title >{{ plugin4install ? "Plugin Installation" : "ImJoy Plugin Management" }} <!-- 在标题栏添加一个关闭按钮 --> <md-button class="md-accent" style="position:absolute; top:8px; right:5px;" @click=" showAddPluginDialog = false; clearPluginUrl(); " ><md-icon>clear</md-icon></md-button ></md-dialog-title > <!-- 以下是对话框的内容部分 --> <!-- 原来的插件对话框有三种添加插件的方式:(1)通过插件模板template编写插件(2)输入插件url地址安装(3)通过插件商店store安装 --> <!-- 这里我们为了代码精简,只保留了第一种,保证能运行一个最简单的插件即可 --> <md-dialog-content> <template v-if="show_plugin_templates"> <md-menu> <!-- 通过模板template添加插件的按钮 --> <md-button class="md-primary md-raised" md-menu-trigger> <md-icon>add</md-icon>Create a new plugin <md-tooltip>Create a new plugin</md-tooltip> </md-button> <!-- 点击上面按钮后弹出的菜单 --> <md-menu-content> <!-- 菜单项会对所有的模板进行遍历展示 --> <!-- 每个菜单项也都会将鼠标点击事件绑定到newPlugin方法上 --> <!-- 该方法会通过createWindow创建plugin-editor类型的窗口,即代码编辑器 --> <md-menu-item @click=" newPlugin(template.code); showAddPluginDialog = false; " v-for="template in plugin_templates" :key="template.name" > <md-icon>{{ template.icon }}</md-icon >{{ template.name }} </md-menu-item> </md-menu-content> </md-menu> <br /> <br /> </template>
</md-dialog-content> </md-dialog> </div> </template>
|