新增请求测试小工具
This commit is contained in:
parent
58eff630d7
commit
40e90fef4f
src
@ -60,21 +60,15 @@ editorConfig.MENU_CONF.uploadImage = {
|
||||
fieldName: "image", // 后端接收字段名
|
||||
|
||||
async customUpload(file, insertFn) {
|
||||
|
||||
const index = imagesCache.value.length; // 当前图片索引
|
||||
|
||||
// 读取图片尺寸
|
||||
const index = imagesCache.value.length;
|
||||
const imageSize = await getImageSize(file);
|
||||
|
||||
// 存入缓存
|
||||
const objectURL = URL.createObjectURL(file); // 生成 blob URL
|
||||
imagesCache.value.push({
|
||||
file,
|
||||
url: objectURL, // 保存 blob URL
|
||||
originalWidth: imageSize.width,
|
||||
originalHeight: imageSize.height
|
||||
originalHeight: imageSize.height,
|
||||
});
|
||||
|
||||
// 生成临时预览 URL
|
||||
const objectURL = URL.createObjectURL(file);
|
||||
insertFn(objectURL, `image-${index}`, objectURL); // 插入编辑器
|
||||
}
|
||||
};
|
||||
@ -155,10 +149,30 @@ const submitBlog = async () => {
|
||||
|
||||
|
||||
let content = editorRef.value.getHtml(); // 获取 HTML 内容
|
||||
const images = [...imagesCache.value]; // 复制图片数组
|
||||
let images = [...imagesCache.value]; // 复制图片数组
|
||||
|
||||
// 解析 `<img>` 并处理宽高
|
||||
// 解析 `<img>` 并提取所有 blob URL
|
||||
const imgTags = content.match(/<img[^>]+>/g) || [];
|
||||
const usedUrls = new Set(); // 记录编辑器中使用的 blob URL
|
||||
|
||||
imgTags.forEach((imgTag) => {
|
||||
const srcMatch = imgTag.match(/src=["']([^"']+)["']/);
|
||||
if (srcMatch) {
|
||||
usedUrls.add(srcMatch[1]); // 将使用的 blob URL 添加到 Set 中
|
||||
}
|
||||
});
|
||||
|
||||
// 清理 imagesCache 中未被使用的图片
|
||||
images = images.filter((img) => {
|
||||
const isUsed = usedUrls.has(img.url);
|
||||
if (!isUsed) {
|
||||
URL.revokeObjectURL(img.url); // 释放未使用的 blob URL
|
||||
}
|
||||
return isUsed; // 只保留编辑器中仍在使用的图片
|
||||
});
|
||||
|
||||
// 更新 imagesCache
|
||||
imagesCache.value = images;
|
||||
|
||||
// 创建 blob URL 到索引的映射
|
||||
const urlToIndexMap = new Map();
|
||||
@ -185,8 +199,8 @@ const submitBlog = async () => {
|
||||
const styleMatch = imgTag.match(/style=["']([^"']+)["']/);
|
||||
let width = "", height = "";
|
||||
|
||||
// 获取图片的原始尺寸(从 images 中根据 blob URL 匹配)
|
||||
const imageData = images.find((img) => URL.createObjectURL(img.file) === src);
|
||||
// 从 images 中根据保存的 url 匹配图片数据
|
||||
const imageData = images.find((img) => img.url === src); // 使用保存的 url 比较
|
||||
const originalWidth = imageData?.originalWidth || 0;
|
||||
const originalHeight = imageData?.originalHeight || 0;
|
||||
|
||||
@ -217,7 +231,6 @@ const submitBlog = async () => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 2️⃣ 构造表单数据
|
||||
const formData = new FormData();
|
||||
formData.append("title", title);
|
||||
@ -225,20 +238,21 @@ const submitBlog = async () => {
|
||||
formData.append("allow_comments", allowComments);
|
||||
formData.append("draft", true);
|
||||
|
||||
images.forEach((imgData, index) => {
|
||||
formData.append(`images[${index}]`, imgData.file); // 按索引存储图片
|
||||
console.log(images);
|
||||
images.forEach((imgData) => {
|
||||
formData.append(`images`, imgData.file); // 按索引存储图片
|
||||
});
|
||||
|
||||
console.log(Object.fromEntries(formData.entries()));
|
||||
// 3️⃣ 发送请求
|
||||
|
||||
// 3️⃣ 发送请求
|
||||
api.post('/blogs', formData, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
}).then(response => {
|
||||
if (response.code === 0) {
|
||||
swal.window('success', `提交成功, 博客id${response.blogId || '未找到blogId字段'}`);
|
||||
swal.window('success', `提交成功, 博客id${response.blogId || '未找到blogId字段'}`, 'ok', '好的');
|
||||
return;
|
||||
}
|
||||
swal.window('error', '提交失败', `code字段为${response.code}; 错误信息: ${response.message}`, 'ok', '好的');
|
||||
|
@ -1,7 +1,12 @@
|
||||
<script setup>
|
||||
import {ref} from "vue";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {blogImage} from "../utils/imageResource.js";
|
||||
|
||||
const blogDisplay = ref('<h2>654654654</h2><ul><li><strong>砍砍价考核表计划表</strong></li></ul><ol><li><strong>1第三方代发</strong></li><li><strong>水电费水电费sd f收到f</strong></li><li><strong>收到f sd </strong></li><li><strong>11234</strong></li></ol>')
|
||||
const blogDisplay = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -13,6 +13,7 @@ const searchQuery = ref('');
|
||||
const tools = ref([
|
||||
{ id: 1, title: 'GPA在线计算器', description: '手动输入在线算', image: null, category: ['计算'] },
|
||||
{ id: 2, title: 'PDF页面提取器', description: '提取指定页和封面', image: null, category: ['提取', 'pdf'] },
|
||||
{ id: 3, title: '请求测试器', description: '自定义请求测试', image: null, category: ['开发', '网络'] },
|
||||
]);
|
||||
|
||||
onMounted(() => {
|
||||
|
24
src/pages/blogPages/SingleBlog_page.vue
Normal file
24
src/pages/blogPages/SingleBlog_page.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
|
||||
const blogDisplay = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<div v-html="blogDisplay"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
490
src/pages/toolPages/RequestTester/requestTester_page.vue
Normal file
490
src/pages/toolPages/RequestTester/requestTester_page.vue
Normal file
@ -0,0 +1,490 @@
|
||||
<template>
|
||||
<div class="request-tester">
|
||||
<!-- 左侧操作区 -->
|
||||
<div class="operation-area">
|
||||
<!-- URL 输入 -->
|
||||
<div class="form-group">
|
||||
<label>URL</label>
|
||||
<input v-model="url" placeholder="请输入目标 URL" />
|
||||
</div>
|
||||
|
||||
<!-- 请求方法选择 -->
|
||||
<div class="form-group">
|
||||
<label>请求方法</label>
|
||||
<select v-model="method">
|
||||
<option value="GET">GET</option>
|
||||
<option value="POST">POST</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="DELETE">DELETE</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 请求头设置 -->
|
||||
<div class="form-group">
|
||||
<label>请求头</label>
|
||||
<div v-for="(header, index) in headers" :key="index" class="key-value-pair">
|
||||
<input v-model="header.key" placeholder="键" />
|
||||
<input v-model="header.value" placeholder="值" />
|
||||
<button @click="removeHeader(index)">删除</button>
|
||||
</div>
|
||||
<button @click="addHeader">添加请求头</button>
|
||||
</div>
|
||||
|
||||
<!-- 请求体类型选择 -->
|
||||
<div class="form-group" v-if="method !== 'GET' && method !== 'DELETE'">
|
||||
<label>请求体类型</label>
|
||||
<select v-model="bodyType">
|
||||
<option value="json">JSON</option>
|
||||
<option value="formdata">FormData</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 请求体设置:JSON -->
|
||||
<div class="form-group" v-if="method !== 'GET' && method !== 'DELETE' && bodyType === 'json'">
|
||||
<label>请求体 (JSON)</label>
|
||||
<textarea v-model="body" placeholder="请输入 JSON 文本"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- 请求体设置:FormData -->
|
||||
<div class="form-group" v-if="method !== 'GET' && method !== 'DELETE' && bodyType === 'formdata'">
|
||||
<label>请求体 (FormData)</label>
|
||||
<div v-for="(item, index) in formDataItems" :key="index" class="formdata-item">
|
||||
<!-- 键名 -->
|
||||
<input v-model="item.key" placeholder="键名" />
|
||||
|
||||
<!-- 类型选择 -->
|
||||
<select v-model="item.type" @change="resetValue(item)">
|
||||
<option value="pair">普通键值对</option>
|
||||
<option value="array">数组</option>
|
||||
</select>
|
||||
|
||||
<!-- 普通键值对输入 -->
|
||||
<div v-if="item.type === 'pair'">
|
||||
<input v-if="!item.isFile" v-model="item.value" placeholder="值" />
|
||||
<input v-else type="file" @change="handleFileChange(item, $event)" />
|
||||
<div style="margin: 10px 0"/>
|
||||
<button @click="item.isFile = !item.isFile">
|
||||
{{ item.isFile ? '切换为文本' : '切换为文件' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 数组输入 -->
|
||||
<div v-if="item.type === 'array'">
|
||||
<div v-for="(val, valIndex) in item.value" :key="valIndex" class="array-item">
|
||||
<input v-if="!val.isFile" v-model="val.content" placeholder="数组值" />
|
||||
<input v-else type="file" @change="handleArrayFileChange(item, valIndex, $event)" />
|
||||
<button @click="val.isFile = !val.isFile">
|
||||
{{ val.isFile ? '切换为文本' : '切换为文件' }}
|
||||
</button>
|
||||
<button @click="removeArrayItem(item, valIndex)">删除</button>
|
||||
</div>
|
||||
<button @click="addArrayItem(item)">添加数组项</button>
|
||||
</div>
|
||||
|
||||
<!-- 删除键值对 -->
|
||||
<button @click="removeFormDataItem(index)">删除键值对</button>
|
||||
</div>
|
||||
<button @click="addFormDataItem">添加键值对</button>
|
||||
</div>
|
||||
|
||||
<!-- 查询参数设置 -->
|
||||
<div class="form-group">
|
||||
<label>查询参数</label>
|
||||
<div v-for="(param, index) in params" :key="index" class="key-value-pair">
|
||||
<input v-model="param.key" placeholder="键" />
|
||||
<input v-model="param.value" placeholder="值" />
|
||||
<button @click="removeParam(index)">删除</button>
|
||||
</div>
|
||||
<button @click="addParam">添加参数</button>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="actions">
|
||||
<button @click="sendRequest">发送请求</button>
|
||||
<button @click="savePreset">保存预设</button>
|
||||
</div>
|
||||
|
||||
<!-- 响应结果 -->
|
||||
<div class="response" v-if="response">
|
||||
<h3>响应结果</h3>
|
||||
<pre>{{ response }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧储存栏 -->
|
||||
<div class="storage-area">
|
||||
<h3>储存栏</h3>
|
||||
<div v-if="!requestTesterPresets || Object.keys(requestTesterPresets).length === 0">暂无预设</div>
|
||||
<div v-else v-for="(preset, name) in requestTesterPresets" :key="name" class="preset-item">
|
||||
<span @click="loadPreset(name)" class="preset-name">{{ name }}</span>
|
||||
<button @click="deletePreset(name)">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, computed } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import axios from 'axios';
|
||||
import Swal from 'sweetalert2';
|
||||
import swal from "../../../utils/sweetalert.js";
|
||||
|
||||
export default {
|
||||
name: 'RequestTester',
|
||||
setup() {
|
||||
const store = useStore();
|
||||
|
||||
// 数据定义
|
||||
const url = ref('');
|
||||
const method = ref('GET');
|
||||
const headers = ref([{ key: '', value: '' }]);
|
||||
const bodyType = ref('json'); // 请求体类型:json 或 formdata
|
||||
const body = ref(''); // JSON 文本
|
||||
const formDataItems = ref([]); // FormData 键值对
|
||||
const params = ref([{ key: '', value: '' }]);
|
||||
const response = ref(null);
|
||||
|
||||
// 从 Vuex 获取 requestTester 的预设
|
||||
const requestTesterPresets = computed(() => store.state.demosLocal.requestTester || {});
|
||||
|
||||
// 请求头操作
|
||||
const addHeader = () => headers.value.push({ key: '', value: '' });
|
||||
const removeHeader = (index) => headers.value.splice(index, 1);
|
||||
|
||||
// 查询参数操作
|
||||
const addParam = () => params.value.push({ key: '', value: '' });
|
||||
const removeParam = (index) => params.value.splice(index, 1);
|
||||
|
||||
// FormData 键值对操作
|
||||
const addFormDataItem = () => {
|
||||
formDataItems.value.push({ key: '', type: 'pair', value: '', isFile: false });
|
||||
};
|
||||
const removeFormDataItem = (index) => {
|
||||
formDataItems.value.splice(index, 1);
|
||||
};
|
||||
const resetValue = (item) => {
|
||||
if (item.type === 'pair') {
|
||||
item.value = '';
|
||||
item.isFile = false;
|
||||
} else if (item.type === 'array') {
|
||||
item.value = [{ content: '', isFile: false }];
|
||||
}
|
||||
};
|
||||
const addArrayItem = (item) => {
|
||||
if (!item.value) item.value = [];
|
||||
item.value.push({ content: '', isFile: false });
|
||||
};
|
||||
const removeArrayItem = (item, index) => {
|
||||
item.value.splice(index, 1);
|
||||
};
|
||||
const handleFileChange = (item, event) => {
|
||||
item.value = event.target.files[0];
|
||||
};
|
||||
const handleArrayFileChange = (item, index, event) => {
|
||||
item.value[index].content = event.target.files[0];
|
||||
};
|
||||
|
||||
// 发送请求
|
||||
const sendRequest = async () => {
|
||||
response.value = '等待响应...'; // 发送请求前显示“等待响应”
|
||||
|
||||
try {
|
||||
let finalUrl = url.value;
|
||||
const headersObj = headers.value.reduce((acc, h) => {
|
||||
if (h.key && h.value) acc[h.key] = h.value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// 处理查询参数
|
||||
const queryParams = params.value
|
||||
.filter((p) => p.key && p.value)
|
||||
.reduce((acc, p) => {
|
||||
acc[p.key] = p.value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
let axiosConfig = {
|
||||
method: method.value,
|
||||
url: finalUrl,
|
||||
headers: headersObj,
|
||||
params: queryParams,
|
||||
};
|
||||
|
||||
// 处理请求体
|
||||
if (method.value !== 'GET' && method.value !== 'DELETE') {
|
||||
if (bodyType.value === 'json') {
|
||||
axiosConfig.data = body.value ? JSON.parse(body.value) : {};
|
||||
if (!headersObj['Content-Type']) {
|
||||
axiosConfig.headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
} else if (bodyType.value === 'formdata') {
|
||||
const formData = new FormData();
|
||||
formDataItems.value.forEach((item) => {
|
||||
if (item.key) {
|
||||
if (item.type === 'pair' && item.value) {
|
||||
formData.append(item.key, item.value);
|
||||
} else if (item.type === 'array' && item.value.length) {
|
||||
item.value.forEach((val) => {
|
||||
if (val.content) {
|
||||
formData.append(item.key + '[]', val.content);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
axiosConfig.data = formData;
|
||||
}
|
||||
}
|
||||
|
||||
const res = await axios(axiosConfig);
|
||||
response.value = JSON.stringify(res.data, null, 2);
|
||||
} catch (error) {
|
||||
response.value = `错误: ${error.message}`;
|
||||
}
|
||||
};
|
||||
|
||||
// 保存预设
|
||||
const savePreset = async () => {
|
||||
const result = await Swal.fire({
|
||||
title: '请输入预设名称',
|
||||
input: 'text',
|
||||
inputLabel: '预设名称',
|
||||
inputPlaceholder: '请输入您的预设名称...',
|
||||
showCancelButton: true,
|
||||
cancelButtonText: '取消',
|
||||
confirmButtonText: '确定',
|
||||
inputValidator: (value) => !value && '预设名称不能为空!',
|
||||
});
|
||||
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
const presetName = result.value;
|
||||
const preset = {
|
||||
url: url.value,
|
||||
method: method.value,
|
||||
headers: [...headers.value],
|
||||
bodyType: bodyType.value,
|
||||
body: body.value,
|
||||
formDataItems: formDataItems.value.map((item) => ({
|
||||
key: item.key,
|
||||
type: item.type,
|
||||
value: item.type === 'pair' ? (item.isFile ? 'File' : item.value) : item.value.map((v) => (v.isFile ? 'File' : v.content)),
|
||||
})), // 仅保存文件名或文本
|
||||
params: [...params.value],
|
||||
};
|
||||
|
||||
store.commit('setLocalDemoValue', {
|
||||
demo: 'requestTester',
|
||||
value: { [presetName]: preset },
|
||||
});
|
||||
};
|
||||
|
||||
// 加载预设
|
||||
const loadPreset = (name) => {
|
||||
const preset = requestTesterPresets.value[name];
|
||||
if (preset) {
|
||||
url.value = preset.url;
|
||||
method.value = preset.method;
|
||||
headers.value = [...preset.headers];
|
||||
bodyType.value = preset.bodyType;
|
||||
body.value = preset.body;
|
||||
formDataItems.value = preset.formDataItems.map((item) => ({
|
||||
key: item.key,
|
||||
type: item.type,
|
||||
value: item.type === 'pair' ? '' : [], // 加载时重置文件和数组内容
|
||||
isFile: item.type === 'pair' && item.value === 'File',
|
||||
}));
|
||||
params.value = [...preset.params];
|
||||
response.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 删除预设
|
||||
const deletePreset = (name) => {
|
||||
swal.window('info', '确定删除?', `删除预设"${name}"`, '确定', '取消').then(result => {
|
||||
if (result.isConfirmed) {
|
||||
store.commit('deleteLocalDemoValue', {
|
||||
demo: 'requestTester',
|
||||
value: name,
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
return {
|
||||
url,
|
||||
method,
|
||||
headers,
|
||||
bodyType,
|
||||
body,
|
||||
formDataItems,
|
||||
params,
|
||||
response,
|
||||
requestTesterPresets,
|
||||
addHeader,
|
||||
removeHeader,
|
||||
addParam,
|
||||
removeParam,
|
||||
addFormDataItem,
|
||||
removeFormDataItem,
|
||||
resetValue,
|
||||
addArrayItem,
|
||||
removeArrayItem,
|
||||
handleFileChange,
|
||||
handleArrayFileChange,
|
||||
sendRequest,
|
||||
savePreset,
|
||||
loadPreset,
|
||||
deletePreset,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 默认深色模式 */
|
||||
:root {
|
||||
--bg-color: #2c2c2c;
|
||||
--text-color: #ffffff;
|
||||
--input-bg: #3c3c3c;
|
||||
--border-color: #555;
|
||||
--button-bg: #4a90e2;
|
||||
--button-hover: #357abd;
|
||||
}
|
||||
|
||||
/* 浅色模式 */
|
||||
.theme-light {
|
||||
--bg-color: #ffffff;
|
||||
--text-color: #333333;
|
||||
--input-bg: #f0f0f0;
|
||||
--border-color: #ccc;
|
||||
--button-bg: #4a90e2;
|
||||
--button-hover: #357abd;
|
||||
}
|
||||
|
||||
.request-tester {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
height: calc(100vh - 60px);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.operation-area {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.storage-area {
|
||||
width: 250px;
|
||||
padding: 20px;
|
||||
border-left: 1px solid var(--border-color);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
background-color: var(--input-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
height: 100px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.key-value-pair {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.key-value-pair input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.formdata-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.formdata-item input {
|
||||
width: calc(100% - 18px);
|
||||
}
|
||||
|
||||
.array-item {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 6px 12px;
|
||||
background-color: var(--button-bg);
|
||||
color: #fff;
|
||||
border: gray solid 1px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.theme-light button {
|
||||
color: black;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: var(--button-hover);
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.response {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.response pre {
|
||||
background-color: var(--input-bg);
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.preset-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.preset-name {
|
||||
cursor: pointer;
|
||||
color: var(--button-bg);
|
||||
}
|
||||
|
||||
.preset-name:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
@ -4,6 +4,7 @@ import AuthService from "../../services/auth.js";
|
||||
import Home from '../pages/Home.vue';
|
||||
import Login from "../pages/Login.vue";
|
||||
import Blog_home from "../pages/Blog_home.vue";
|
||||
|
||||
import Account from "../pages/accountPages/Account.vue";
|
||||
import Account_selfpage from "../pages/accountPages/Account_selfpage.vue";
|
||||
import Account_worksmanage from "../pages/accountPages/Account_worksmanage.vue";
|
||||
@ -12,14 +13,19 @@ import Account_draft from "../pages/accountPages/Account_draft.vue";
|
||||
import Account_userInfo from "../pages/accountPages/Account_userInfo.vue";
|
||||
import Account_admin_uploadLog from "../pages/accountPages/Account_admin_uploadLog.vue";
|
||||
import Account_admin_userManage from "../pages/accountPages/Account_admin_userManage.vue";
|
||||
|
||||
import Projects from "../pages/Projects_home.vue";
|
||||
|
||||
import Demos_home from "../pages/Demos_home.vue";
|
||||
import Board_page from "../pages/demoPages/messageBoard/Board_page.vue";
|
||||
import Pod_page from "../pages/demoPages/podExercise/Pod_page.vue";
|
||||
import Pod_quiz from "../pages/demoPages/podExercise/Quiz.vue";
|
||||
|
||||
import Tools_home from "../pages/Tools_home.vue";
|
||||
import GpaCalculator_page from "../pages/toolPages/gpaCalculator/gpaCalculator_page.vue";
|
||||
import PdfEx_page from "../pages/toolPages/pdfExtractor/pdfEx_page.vue";
|
||||
import RequestTester_page from "../pages/toolPages/RequestTester/requestTester_page.vue";
|
||||
|
||||
import About from "../pages/About.vue";
|
||||
import Editor from "../pages/Editor.vue";
|
||||
import NotFound from "../pages/errorPages/notFound.vue";
|
||||
@ -81,6 +87,8 @@ const routes = [
|
||||
{path: "gpa", component: GpaCalculator_page},
|
||||
{path: "2", component: PdfEx_page},
|
||||
{path: "pdf-extractor", component: PdfEx_page},
|
||||
{path: "3", component: RequestTester_page},
|
||||
{path: "request-tester", component: RequestTester_page},
|
||||
]
|
||||
}, {
|
||||
path: '/about',
|
||||
|
@ -38,6 +38,9 @@ const store = createStore({
|
||||
setLocalDemoValue(state, obj) {
|
||||
state.demosLocal[obj.demo] = {...state.demosLocal[obj.demo], ...obj.value}
|
||||
},
|
||||
deleteLocalDemoValue(state, obj) {
|
||||
delete state.demosLocal[obj.demo][obj.value];
|
||||
},
|
||||
saveEdit(state, obj) {
|
||||
state.editStore = {...state.editStore, ...obj};
|
||||
},
|
||||
|
5
src/utils/imageResource.js
Normal file
5
src/utils/imageResource.js
Normal file
@ -0,0 +1,5 @@
|
||||
import {getDomain} from "./getDomain.js";
|
||||
|
||||
export function blogImage(id) {
|
||||
return `https://${getDomain()}/data/blog/images/${id}`;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user