diff --git a/oab/src/api/upload.rs b/oab/src/api/upload.rs index c3324c1..4af8421 100644 --- a/oab/src/api/upload.rs +++ b/oab/src/api/upload.rs @@ -7,11 +7,12 @@ // use actix_multipart::form::{tempfile::TempFile, MultipartForm}; + use actix_web::{post, web, Responder}; use proc::access_read; use tracing::{info, warn}; -use crate::{AppState, Error, Result}; +use crate::{models::Token, AppState, Error, Result}; #[derive(Debug, MultipartForm)] struct UploadForm { @@ -22,27 +23,28 @@ struct UploadForm { #[access_read("app")] async fn save_files( MultipartForm(form): MultipartForm, + t: web::ReqData, stat: web::Data, ) -> Result { let l = form.files.len(); + let t = t.into_inner(); let mut res: Vec = Vec::new(); info!("!|||||||||||_{}_|", l); - for f in form.files { - info!("saving to {:#?}", f); - let fname = f.file_name.unwrap(); - let path = format!("{}tmp/{}", stat.media_path, fname); + form.files.into_iter().for_each(|v| { + let fname = v.file_name.unwrap_or("unknown".to_string()); + let path = format!("{}tmp/{}.{}", stat.media_path, t.id, fname); info!("saving to {path}"); - match f.file.persist(path) { - Ok(t) => { - info!("{:#?}", t); - res.push(format!("/media/tmp/{}", fname)) + match v.file.persist(path) { + Ok(p) => { + info!("{:#?}", p); + res.push(format!("/media/tmp/{}.{}", t.id, fname)) } Err(e) => { warn!("{}", e); - return Err(Error::InternalServerError); + // return Err(Error::InternalServerError); } }; - } + }); Ok(web::Json(res)) } diff --git a/oab/src/result.rs b/oab/src/result.rs index 5a36e18..d4792ad 100644 --- a/oab/src/result.rs +++ b/oab/src/result.rs @@ -162,6 +162,12 @@ impl From for Error { } } +impl From for Error { + fn from(e: actix_multipart::MultipartError) -> Self { + Error::BusinessException(format!("{:?}", e)) + } +} + impl From> for Error { fn from(e: Box) -> Self { Error::BusinessException(format!("{}", e)) diff --git a/oaweb/package.json b/oaweb/package.json index 17544d3..d652976 100644 --- a/oaweb/package.json +++ b/oaweb/package.json @@ -25,6 +25,7 @@ "mitt": "^3.0.1", "pinia": "^2.0.11", "quasar": "^2.6.0", + "vite-plugin-rewrite-all": "^1.0.1", "vue": "^3.0.0", "vue-i18n": "^9.2.2", "vue-router": "^4.0.0", diff --git a/oaweb/public/doc/markdown.md b/oaweb/public/doc/markdown.md index 840497b..4b14f3a 100644 --- a/oaweb/public/doc/markdown.md +++ b/oaweb/public/doc/markdown.md @@ -20,18 +20,18 @@ **示例** ``` -[!!#ff0000 红色超链接!!](http://www.qq.com) -[!!#ffffff !!!#000000 黑底白字超链接!!!!!](http://www.qq.com) -[新窗口打开](http://www.qq.com){target=_blank} +[!!#ff0000 红色超链接!!](http://www.google.com) +[!!#ffffff !!!#000000 黑底白字超链接!!!!!](http://www.google.com) +[新窗口打开](http://www.google.com){target=_blank} 鞋子 !32 特大号! 大头 ^`儿子`^ 和小头 ^^`爸爸`^^ 爱在~~西元前~~**当下** ``` **效果** -[!!#ff0000 红色超链接!!](http://www.qq.com) -[!!#ffffff !!!#000000 黑底白字超链接!!!!!](http://www.qq.com) -[新窗口打开](http://www.qq.com){target=_blank} +[!!#ff0000 红色超链接!!](http://www.google.com) +[!!#ffffff !!!#000000 黑底白字超链接!!!!!](http://www.google.com) +[新窗口打开](http://www.google.com){target=_blank} 鞋子 !32 特大号! 大头 ^`儿子`^ 和小头 ^^`爸爸`^^ 爱在~~西元前~~**当下** @@ -59,21 +59,21 @@ **示例** ``` -这是 [腾讯网](https://www.qq.com) 的链接。 +这是 [Google](https://www.google.com) 的链接。 这是 [一个引用的][引用一个链接] 的链接。 -这是一个包含中文的链接,中文 -直接识别成链接:https://www.qq.com?param=中文,中文 用空格结束 +这是一个包含中文的链接,中文 +直接识别成链接:https://www.google.com?param=中文,中文 用空格结束 [引用一个链接] -[引用一个链接]: https://www.qq.com +[引用一个链接]: https://www.google.com ``` **效果** -这是 [腾讯网](https://www.qq.com) 的链接。 +这是 [Google](https://www.google.com) 的链接。 这是 [一个引用的][引用一个链接] 的链接。 -这是一个包含中文的链接,中文 -直接识别成链接:https://www.qq.com?param=中文,中文 用空格结束 +这是一个包含中文的链接,中文 +直接识别成链接:https://www.google.com?param=中文,中文 用空格结束 [引用一个链接] -[引用一个链接]: https://www.qq.com +[引用一个链接]: https://www.google.com --- @@ -217,33 +217,33 @@ **示例** ``` -标准图片 ![一条dog#100px](images/demo-dog.png) -设置图片大小(相对大小&绝对大小) ![一条dog#10%#50px](images/demo-dog.png) +标准图片 ![一条dog#100px](/cherry/images/demo-dog.png) +设置图片大小(相对大小&绝对大小) ![一条dog#10%#50px](/cherry/images/demo-dog.png) 设置图片对齐方式: **左对齐+边框** -![一条dog#auto#100px#left#border](images/demo-dog.png) +![一条dog#auto#100px#left#border](/cherry/images/demo-dog.png) **居中+边框+阴影** -![一条dog#auto#100px#center#B#shadow](images/demo-dog.png) +![一条dog#auto#100px#center#B#shadow](/cherry/images/demo-dog.png) **右对齐+边框+阴影+圆角** -![一条dog#auto#100px#right#B#S#radius](images/demo-dog.png) +![一条dog#auto#100px#right#B#S#radius](/cherry/images/demo-dog.png) **浮动左对齐+边框+阴影+圆角** -![一条dog#auto#100px#float-left#B#S#R](images/demo-dog.png) +![一条dog#auto#100px#float-left#B#S#R](/cherry/images/demo-dog.png) 开心也是一天,不开心也是一天 这样就过了两天,汪 ``` **效果** -标准图片 ![一条dog#100px](images/demo-dog.png) -设置图片大小(相对大小&绝对大小) ![一条dog#10%#50px](images/demo-dog.png) +标准图片 ![一条dog#100px](/cherry/images/demo-dog.png) +设置图片大小(相对大小&绝对大小) ![一条dog#10%#50px](/cherry/images/demo-dog.png) 设置图片对齐方式: **左对齐+边框** -![一条dog#auto#100px#left#border](images/demo-dog.png) +![一条dog#auto#100px#left#border](/cherry/images/demo-dog.png) **居中+边框+阴影** -![一条dog#auto#100px#center#B#shadow](images/demo-dog.png) +![一条dog#auto#100px#center#B#shadow](/cherry/images/demo-dog.png) **右对齐+边框+阴影+圆角** -![一条dog#auto#100px#right#B#S#radius](images/demo-dog.png) +![一条dog#auto#100px#right#B#S#radius](/cherry/images/demo-dog.png) **浮动左对齐+边框+阴影+圆角** -![一条dog#auto#100px#float-left#B#S#R](images/demo-dog.png) +![一条dog#auto#100px#float-left#B#S#R](/cherry/images/demo-dog.png) 开心也是一天,不开心也是一天 这样就过了两天,汪 @@ -443,14 +443,14 @@ $$ **示例** ``` -这是个演示视频 !video[不带封面演示视频](images/demo.mp4) -这是个演示视频 !video[带封面演示视频](images/demo.mp4){poster=images/demo-dog.png} +这是个演示视频 !video[不带封面演示视频](/cherry/images/demo.mp4) +这是个演示视频 !video[带封面演示视频](/cherry/images/demo.mp4){poster=images/demo-dog.png} 这是个假音频!audio[描述](视频链接地址) ``` **效果** -这是个演示视频 !video[不带封面演示视频](images/demo.mp4) -这是个演示视频 !video[带封面演示视频](images/demo.mp4){poster=images/demo-dog.png} +这是个演示视频 !video[不带封面演示视频](/cherry/images/demo.mp4) +这是个演示视频 !video[带封面演示视频](/cherry/images/demo.mp4){poster=images/demo-dog.png} 这是个假音频!audio[描述](视频链接地址) @@ -679,7 +679,7 @@ title 饼图 ## 通过快捷按钮修改字体样式 -![bubble menu](images/feature_font.png) +![bubble menu](/cherry/images/feature_font.png) ----- @@ -692,7 +692,7 @@ title 饼图 - 可以拖拽调整预览区域的宽度 -![copy and paste](images/feature_copy.gif) +![copy and paste](/cherry/images/feature_copy.gif) ----- @@ -761,24 +761,24 @@ title 饼图 > 其中,`宽度`、`高度`支持:绝对像素值(比如200px)、相对外层容器百分比(比如50%), `对齐方式`候选值有:左对齐(缺省)、右对齐(right)、居中(center)、悬浮左、右对齐(float-left/right) -![图片尺寸](images/feature_image_size.png) +![图片尺寸](/cherry/images/feature_image_size.png) ----- ### 特性 2:根据表格内容生成图表 -![表格图表](images/feature_table_chart.png) +![表格图表](/cherry/images/feature_table_chart.png) ----- ### 特性 3:字体颜色、字体大小 -![字体样式](images/feature_font.png) +![字体样式](/cherry/images/feature_font.png) ------ ## 功能特性 ### 特性 1:复制Html粘贴成MD语法 -![html转md](images/feature_copy.gif) +![html转md](/cherry/images/feature_copy.gif) #### 使用场景 @@ -788,7 +788,7 @@ title 饼图 ---- ### 特性 2:经典换行&常规换行 -![br](images/feature_br.gif) +![br](/cherry/images/feature_br.gif) #### 使用场景 @@ -797,17 +797,17 @@ title 饼图 ----- ### 特性 3: 多光标编辑 -![br](images/feature_cursor.gif) +![br](/cherry/images/feature_cursor.gif) #### 使用场景 想要批量修改?可以试试多光标编辑(快捷键、搜索多光标选中等功能正在开发中) ### 特性 4:图片尺寸 -![wysiwyg](images/feature_image_wysiwyg.gif) +![wysiwyg](/cherry/images/feature_image_wysiwyg.gif) ### 特性 5:导出 -![wysiwyg](images/feature_export.png) +![wysiwyg](/cherry/images/feature_export.png) ------- @@ -817,10 +817,10 @@ title 饼图 > CherryMarkdown会判断用户到底变更了哪个段落,做到只渲染变更的段落,从而提升修改时的渲染性能 -![wysiwyg](images/feature_myers.png) +![wysiwyg](/cherry/images/feature_myers.png) ### 局部更新 > CherryMarkdown利用virtual dom机制实现对预览区域需要变更的内容进行局部更新的功能,从而减少了浏览器Dom操作,提高了修改时预览内容更新的性能 -![wysiwyg](images/feature_vdom.gif) +![wysiwyg](/cherry/images/feature_vdom.gif) diff --git a/oaweb/quasar.config.js b/oaweb/quasar.config.js index b8fbf5f..d3d726d 100644 --- a/oaweb/quasar.config.js +++ b/oaweb/quasar.config.js @@ -11,6 +11,7 @@ const { configure } = require('quasar/wrappers'); const path = require('path'); +const pluginRewriteAll = require('vite-plugin-rewrite-all'); module.exports = configure(function(/* ctx */) { return { @@ -68,7 +69,7 @@ module.exports = configure(function(/* ctx */) { node: 'node16' }, - vueRouterMode: 'hash', // available values: 'hash', 'history' + vueRouterMode: 'history', // available values: 'hash', 'history' // vueRouterBase, // vueDevtools, // vueOptionsAPI: false, @@ -93,6 +94,7 @@ module.exports = configure(function(/* ctx */) { // viteVuePluginOptions: {}, vitePlugins: [ + pluginRewriteAll.default(), ['@intlify/vite-plugin-vue-i18n', { // if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false` // compositionOnly: false, diff --git a/oaweb/src/App.vue b/oaweb/src/App.vue index a21417d..40bd78e 100644 --- a/oaweb/src/App.vue +++ b/oaweb/src/App.vue @@ -14,12 +14,13 @@ $q.iconMapFn = (iconName) => { // your custom approach, the following // is just an example: - if (iconName.startsWith('app:') === true) { + if (iconName.startsWith('v-') === true) { // we strip the "app:" part - const name = iconName.substring(4) + const name = iconName.substring(2) + console.log(name) return { - cls: 'my-app-icon ' + name + icon: 'svguse:#icon-' + name } } } @@ -39,10 +40,10 @@ body, } .page-h1 { - font-size: 1.5rem; - line-height: 2rem; + font-size: 2.5rem; + line-height: 2.5rem; margin-left: 2.5rem; - margin-top: 1.25rem; - margin-bottom: 1.25rem; + margin-top: 1.5rem; + margin-bottom: 2rem; } diff --git a/oaweb/src/assets/icon.js b/oaweb/src/assets/icon.js index 47670c9..0ebbf04 100644 --- a/oaweb/src/assets/icon.js +++ b/oaweb/src/assets/icon.js @@ -1 +1 @@ -window._iconfont_svg_string_3335115='',function(c){var t=(t=document.getElementsByTagName("script"))[t.length-1],l=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var e,o,a,h,i,n=function(t,l){l.parentNode.insertBefore(t,l)};if(l&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}e=function(){var t,l=document.createElement("div");l.innerHTML=c._iconfont_svg_string_3335115,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(t=document.body).firstChild?n(l,t.firstChild):t.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(e,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),e()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(a=e,h=c.document,i=!1,s(),h.onreadystatechange=function(){"complete"==h.readyState&&(h.onreadystatechange=null,d())})}function d(){i||(i=!0,a())}function s(){try{h.documentElement.doScroll("left")}catch(t){return void setTimeout(s,50)}d()}}(window); \ No newline at end of file +window._iconfont_svg_string_3335115='',function(l){var c=(c=document.getElementsByTagName("script"))[c.length-1],h=c.getAttribute("data-injectcss"),c=c.getAttribute("data-disable-injectsvg");if(!c){var t,a,o,i,e,v=function(c,h){h.parentNode.insertBefore(c,h)};if(h&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}t=function(){var c,h=document.createElement("div");h.innerHTML=l._iconfont_svg_string_3335115,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(c=document.body).firstChild?v(h,c.firstChild):c.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(a=function(){document.removeEventListener("DOMContentLoaded",a,!1),t()},document.addEventListener("DOMContentLoaded",a,!1)):document.attachEvent&&(o=t,i=l.document,e=!1,s(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,d())})}function d(){e||(e=!0,o())}function s(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(s,50)}d()}}(window); \ No newline at end of file diff --git a/oaweb/src/boot/api/axios.ts b/oaweb/src/boot/api/axios.ts index 4cbb923..415d495 100644 --- a/oaweb/src/boot/api/axios.ts +++ b/oaweb/src/boot/api/axios.ts @@ -7,6 +7,7 @@ import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios'; import msg from '@veypi/msg' +import util from 'src/libs/util'; // Be careful when using SSR for cross-request state pollution // due to creating a Singleton instance here; @@ -27,7 +28,7 @@ const proxy = axios.create({ // 请求拦截 const beforeRequest = (config: any) => { // 设置 token - const token = localStorage.getItem('auth_token') + const token = util.getToken() // NOTE 添加自定义头部 token && (config.headers.auth_token = token) // config.headers['auth_token'] = '' diff --git a/oaweb/src/boot/pack.ts b/oaweb/src/boot/pack.ts index 36295e8..671bfe5 100644 --- a/oaweb/src/boot/pack.ts +++ b/oaweb/src/boot/pack.ts @@ -14,15 +14,24 @@ import '../assets/icon.js' import '@veypi/oaer/dist/index.css' import 'cherry-markdown/dist/cherry-markdown.css'; +import oafs from 'src/libs/oafs' import { Cfg } from '@veypi/oaer' +import util from 'src/libs/util.js' +import evt from 'src/libs/evt.js' -conf.timeout = 5000 +oafs.setCfg(util.getToken()) +Cfg.token.value = util.getToken() +conf.timeout = 5000 Cfg.host.value = 'http://' + window.location.host -Cfg.token.value = localStorage.getItem('auth_token') || '' Cfg.uuid.value = 'FR9P5t8debxc11aFF' +evt.on('token', (t) => { + oafs.setCfg(util.getToken()) + Cfg.token.value = util.getToken() +}) + // "async" is optional; // more info on params: https://v2.quasar.dev/quasar-cli/boot-files export default boot(async (/* { app, router, ... } */) => { diff --git a/oaweb/src/components/EssentialLink.vue b/oaweb/src/components/EssentialLink.vue index c2658be..2e3f964 100644 --- a/oaweb/src/components/EssentialLink.vue +++ b/oaweb/src/components/EssentialLink.vue @@ -1,8 +1,8 @@