addAppDialog.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <template>
  2. <div>
  3. <el-dialog
  4. :center="true"
  5. :visible.sync="show"
  6. :close-on-click-modal="false"
  7. width="500px"
  8. class="addNewAppDialog"
  9. >
  10. <div class="a-d-top">
  11. <div class="a-d-topTit">
  12. <div v-if="type === 1">创建新应用</div>
  13. <div v-else>修改应用</div>
  14. </div>
  15. <div class="a-d-t-right">
  16. <span @click="close()">×</span>
  17. </div>
  18. </div>
  19. <div class="bfd_box" v-loading="loading" label-position="top">
  20. <el-form :model="form" :rules="rules" ref="ruleForm">
  21. <div
  22. style="display: flex;width: 100%;justify-content: space-between;align-items: center;"
  23. >
  24. <el-form-item label="应用图标" prop="icon">
  25. <el-input
  26. v-model="form.json.icon"
  27. placeholder="请输入应用图标(可直接粘贴svg或者点击右侧图标上传图片)"
  28. style="width: 500px;"
  29. ></el-input>
  30. </el-form-item>
  31. <div
  32. class="bfd_icon"
  33. v-loading="uploadIconLoading"
  34. @click="uploadIcon()"
  35. >
  36. <!-- svg -->
  37. <span
  38. v-html="form.json.icon"
  39. v-if="isImageOrSvg(form.json.icon) === 1"
  40. ></span>
  41. <!-- 默认图标 -->
  42. <svg
  43. v-if="isImageOrSvg(form.json.icon) === 0"
  44. t="1732605901531"
  45. class="icon"
  46. viewBox="0 0 1024 1024"
  47. version="1.1"
  48. xmlns="http://www.w3.org/2000/svg"
  49. p-id="4275"
  50. width="200"
  51. height="200"
  52. >
  53. <path
  54. d="M179.2 153.6a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V204.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V204.8a153.6 153.6 0 0 1 153.6-153.6z m0 614.4a51.2 51.2 0 0 0-51.2 51.2v128a51.2 51.2 0 0 0 51.2 51.2h128a51.2 51.2 0 0 0 51.2-51.2V716.8a51.2 51.2 0 0 0-51.2-51.2H179.2z m0-102.4h128a153.6 153.6 0 0 1 153.6 153.6v128a153.6 153.6 0 0 1-153.6 153.6H179.2a153.6 153.6 0 0 1-153.6-153.6V716.8a153.6 153.6 0 0 1 153.6-153.6z m611.84-403.4048a51.2 51.2 0 0 0-72.3968 0L646.144 232.2432a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968L791.04 159.744z m72.3968-72.3968l72.3968 72.3968a153.6 153.6 0 0 1 0 217.2416l-72.3968 72.3968a153.6 153.6 0 0 1-217.2416 0l-72.3968-72.3968a153.6 153.6 0 0 1 0-217.2416l72.3968-72.3968a153.6 153.6 0 0 1 217.2416 0zM699.7504 896a51.2 51.2 0 0 1 0 102.4A162.1504 162.1504 0 0 1 537.6 836.2496v-110.8992A162.1504 162.1504 0 0 1 699.7504 563.2h110.8992a162.1504 162.1504 0 0 1 162.1504 162.1504v8.448a51.2 51.2 0 0 1-102.4 0v-8.448c0-33.024-26.7264-59.7504-59.7504-59.7504h-110.8992c-33.024 0-59.7504 26.7264-59.7504 59.7504v110.8992c0 33.024 26.7264 59.7504 59.7504 59.7504z"
  55. fill="#2C6DD2"
  56. p-id="4276"
  57. ></path>
  58. <path
  59. d="M791.4496 160a51.2 51.2 0 0 0-72.3968 0l-72.448 72.3968a51.2 51.2 0 0 0 0 72.3968l72.448 72.3968a51.2 51.2 0 0 0 72.3968 0l72.3968-72.3968a51.2 51.2 0 0 0 0-72.3968l-72.3968-72.3968z"
  60. fill="#20C997"
  61. p-id="4277"
  62. ></path>
  63. </svg>
  64. <!-- 网络图片 -->
  65. <el-image
  66. v-if="isImageOrSvg(form.json.icon) === 2"
  67. style="width: 100%; height: 100%"
  68. :src="form.json.icon"
  69. fit="cover"
  70. ></el-image>
  71. </div>
  72. </div>
  73. <el-form-item label="应用名称" prop="name">
  74. <el-input
  75. v-model="form.name"
  76. placeholder="请输入应用名称"
  77. ></el-input>
  78. </el-form-item>
  79. <div
  80. style="display: flex;width: 100%;justify-content: space-between;"
  81. >
  82. <el-form-item label="应用标签" prop="label">
  83. <el-input
  84. v-model="form.label"
  85. placeholder="请输入应用标签"
  86. style="width: 300px;"
  87. ></el-input>
  88. </el-form-item>
  89. <el-form-item label="应用类型" prop="type">
  90. <el-select
  91. v-model="form.type"
  92. placeholder="请选择应用类型"
  93. style="width: 300px;"
  94. >
  95. <el-option
  96. v-for="item in typeList"
  97. :key="item.id"
  98. :label="item.name"
  99. :value="item.id"
  100. >
  101. </el-option>
  102. </el-select>
  103. </el-form-item>
  104. </div>
  105. <el-form-item label="应用链接" prop="url">
  106. <el-input
  107. v-model="form.url"
  108. placeholder="请输入应用链接"
  109. ></el-input>
  110. </el-form-item>
  111. <el-form-item label="应用简介" prop="detail">
  112. <el-input
  113. type="textarea"
  114. v-model="form.detail"
  115. style="width: 100%;"
  116. :rows="3"
  117. resize="none"
  118. placeholder="请输入应用简介"
  119. ></el-input>
  120. </el-form-item>
  121. <el-form-item
  122. label="可见范围"
  123. style="display: flex;flex-direction: column;align-items: flex-start;"
  124. >
  125. <el-radio-group v-model="form.juri">
  126. <el-radio label="1">私有</el-radio>
  127. <el-radio label="2">公开组织</el-radio>
  128. <el-radio label="3">公开所有人</el-radio>
  129. </el-radio-group>
  130. </el-form-item>
  131. <!-- <el-form-item label="权限设置" style="display: flex;flex-direction: column;align-items: flex-start;">
  132. <el-radio-group v-model="form.json.copy" style="display: flex;flex-direction: column;">
  133. <el-radio label="0" class="radioItem">仅体验(用户仅能使用,不可查看设置内容)</el-radio>
  134. <el-radio label="1" class="radioItem">允许其他用户复制并进行二次创作</el-radio>
  135. </el-radio-group>
  136. </el-form-item> -->
  137. </el-form>
  138. </div>
  139. <div class="bfd_bottom">
  140. <el-button @click="close()">取消</el-button>
  141. <el-button type="primary" @click="submitBtn('ruleForm')"
  142. >保存</el-button
  143. >
  144. </div>
  145. </el-dialog>
  146. </div>
  147. </template>
  148. <script>
  149. let validUrl = (rule, value, callback) => {
  150. if (value) {
  151. // 验证链接是否有效
  152. try {
  153. new URL(value);
  154. callback();
  155. } catch (error) {
  156. return callback(new Error("请输入有效的链接"));
  157. }
  158. }
  159. };
  160. export default {
  161. props: {
  162. typeList: {
  163. type: Array,
  164. default: () => {
  165. return [];
  166. }
  167. }
  168. },
  169. data() {
  170. return {
  171. loading: false,
  172. show: false,
  173. uploadIconLoading: false,
  174. type: 1, //1添加,2编辑
  175. form: {
  176. name: "",
  177. label: "",
  178. detail: "",
  179. url: "",
  180. type: "",
  181. juri: "1",
  182. stand: "cn",
  183. json: {
  184. icon: "",
  185. copy: "0"
  186. }
  187. },
  188. rules: {
  189. name: [{ required: true, message: "请输入应用名称", trigger: "blur" }],
  190. url: [{ required: true, message: "请输入应用链接", trigger: "blur" }],
  191. // nlabel: [
  192. // { required: true, message: "请输入应用标签", trigger: "blur" }
  193. // ],
  194. // ntype: [{ required: true, message: "请选择应用类型", trigger: "blur" }],
  195. // ndetail:[{required:true,message:"请输入应用简介",trigger:"blur"}],
  196. juri: [{ required: true, message: "请选择权限管理", trigger: "blur" }],
  197. url: [
  198. { required: true, message: "请输入应用链接", trigger: "blur" },
  199. { validator: validUrl, trigger: "blur" }
  200. ]
  201. }
  202. };
  203. },
  204. computed: {
  205. isImageOrSvg() {
  206. return value => {
  207. let _result = 0; //啥也不是
  208. if (value) {
  209. const svgPattern = /<svg.*<\/svg>/;
  210. const imagePattern = /\.(jpeg|jpg|gif|png|svg|bmp|webp)$/i; // 图片链接的正则表达式
  211. const urlPattern = /^(http|https):\/\/[^ "]+$/; // 网络地址的正则表达式
  212. if (svgPattern.test(value)) {
  213. _result = 1;
  214. } else if (urlPattern.test(value) && imagePattern.test(value)) {
  215. _result = 2;
  216. }
  217. }
  218. return _result;
  219. };
  220. }
  221. },
  222. methods: {
  223. open(data) {
  224. if (data && data.type === 2) {
  225. if (!data.form.json) {
  226. data.form.json = { icon: "", copy: "0" };
  227. }
  228. if(!data.form.json.icon){
  229. data.form.json.icon = ""
  230. }
  231. if(!data.form.json.copy){
  232. data.form.json.copy = "0"
  233. }
  234. this.form = data.form;
  235. this.type = data.type;
  236. } else {
  237. this.form = {
  238. name: "",
  239. label: "",
  240. detail: "",
  241. url: "",
  242. type: "",
  243. juri: "1",
  244. stand: "cn",
  245. json: {
  246. icon: "",
  247. copy: "0"
  248. }
  249. };
  250. }
  251. this.loading = false;
  252. this.uploadIconLoading = false;
  253. this.show = true;
  254. },
  255. uploadIcon() {
  256. if (this.uploadIconLoading) return this.$message.info("请稍等...");
  257. const input = document.createElement("input");
  258. input.type = "file";
  259. input.accept =
  260. "image/jpeg, image/jpg, image/gif, image/png, image/svg+xml";
  261. input.onchange = async event => {
  262. const file = event.target.files[0];
  263. this.uploadIconLoading = true;
  264. const validImageTypes = /\.(jpeg|jpg|gif|png|svg)$/i; // 定义有效的图片类型正则表达式
  265. if (validImageTypes.test(file.name)) {
  266. let url = await this.uploadFile(file);
  267. if (url) {
  268. this.form.json.icon = url;
  269. }
  270. this.uploadIconLoading = false;
  271. } else {
  272. this.$message.error("请上传有效的图片文件!(jpeg|jpg|gif|png|svg)"); // 提示用户上传有效的图片
  273. }
  274. };
  275. input.click();
  276. },
  277. close(flag = false) {
  278. if (this.loading && !flag) return this.$message.info("请稍等...");
  279. this.show = false;
  280. this.init();
  281. },
  282. init() {
  283. this.form = {
  284. name: "",
  285. label: "",
  286. detail: "",
  287. url: "",
  288. type: "",
  289. juri: "1",
  290. stand: "cn",
  291. json: {
  292. icon: "",
  293. copy: "0"
  294. }
  295. };
  296. this.loading = false;
  297. },
  298. submitBtn(ref) {
  299. if (this.loading) return this.$message.info("请稍等...");
  300. this.$refs[ref].validate(valid => {
  301. if (valid) {
  302. this.loading = true;
  303. this.$emit("success", this.form, this.type);
  304. }
  305. });
  306. },
  307. uploadFile(file) {
  308. return new Promise(resolve => {
  309. var credentials = {
  310. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  311. secretAccessKey: "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"
  312. }; //秘钥形式的登录上传
  313. window.AWS.config.update(credentials);
  314. window.AWS.config.region = "cn-northwest-1"; //设置区域
  315. var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
  316. var _this = this;
  317. if (file) {
  318. // this.loading = true;
  319. var params = {
  320. Key:
  321. file.name.split(".")[0] +
  322. new Date().getTime() +
  323. "." +
  324. file.name.split(".")[file.name.split(".").length - 1],
  325. ContentType: file.type,
  326. Body: file,
  327. "Access-Control-Allow-Credentials": "*",
  328. ACL: "public-read"
  329. }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
  330. var options = {
  331. partSize: 2048 * 1024 * 1024,
  332. queueSize: 2,
  333. leavePartsOnError: true
  334. };
  335. bucket
  336. .upload(params, options)
  337. .on("httpUploadProgress", function(evt) {
  338. //这里可以写进度条
  339. // _this.progressData.value = parseInt((evt.loaded * 100) / evt.total);
  340. // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
  341. })
  342. .send(function(err, data) {
  343. if (err) {
  344. _this.$message.error("上传失败");
  345. resolve(0);
  346. } else {
  347. resolve(data.Location);
  348. }
  349. });
  350. }
  351. });
  352. }
  353. }
  354. };
  355. </script>
  356. <style scoped>
  357. .addNewAppDialog >>> .el-dialog {
  358. min-width: 700px;
  359. /* height: 900px; */
  360. height: 780px;
  361. box-shadow: 0px 0 8px 0px #555555;
  362. border-radius: 8px;
  363. background-color: #fff;
  364. /* top: 0px; */
  365. /* margin: 0 auto; */
  366. overflow: hidden;
  367. }
  368. .addNewAppDialog >>> .el-dialog__body {
  369. height: 100%;
  370. min-width: 700px;
  371. flex-shrink: 0;
  372. box-sizing: border-box;
  373. padding-bottom: 50px;
  374. padding-top: 10px;
  375. }
  376. .addNewAppDialog >>> .el-dialog__header {
  377. display: none !important;
  378. }
  379. .a-d-top {
  380. /* background: #adadad; */
  381. display: flex;
  382. flex-direction: row;
  383. flex-wrap: nowrap;
  384. align-items: center;
  385. justify-content: space-between;
  386. height: 54px;
  387. border-radius: 8px 8px 0 0;
  388. user-select: none;
  389. border-bottom: 1px #ccc solid;
  390. }
  391. .a-d-top >>> .el-input__inner {
  392. width: 320px;
  393. height: 32px;
  394. }
  395. .a-d-top >>> .el-input__icon {
  396. line-height: 32px;
  397. }
  398. .a-d-topTit {
  399. /* width: 171px; */
  400. /* margin-left: 20px; */
  401. height: 32px;
  402. display: flex;
  403. font-weight: bold;
  404. font-size: 20px;
  405. align-items: center;
  406. font-family: PingFang SC;
  407. box-sizing: border-box;
  408. padding: 5px;
  409. line-height: 22px;
  410. justify-content: center;
  411. /* text-align: left; */
  412. }
  413. .a-d-t-right > span {
  414. font-size: 18px;
  415. font-weight: bold;
  416. cursor: pointer;
  417. }
  418. .bfd_bottom {
  419. display: flex;
  420. justify-content: flex-end;
  421. }
  422. .bfd_icon {
  423. width: 70px;
  424. height: 70px;
  425. box-sizing: border-box;
  426. padding: 5px;
  427. margin-right: 40px;
  428. cursor: pointer;
  429. }
  430. .bfd_icon > svg {
  431. width: 100%;
  432. height: 100%;
  433. }
  434. .bfd_icon > span {
  435. width: 100%;
  436. height: 100%;
  437. display: block;
  438. }
  439. .bfd_icon > span >>> svg {
  440. width: 100%;
  441. height: 100%;
  442. }
  443. .switchForm{
  444. display: flex;
  445. align-items: center;
  446. }
  447. .switchForm>span{
  448. margin-left: 10px;
  449. }
  450. .radioItem{
  451. margin-bottom: 10px;
  452. }
  453. </style>