Files
gen_short_link/src/views/GenShortLink.vue
2023-02-13 17:29:41 +08:00

392 lines
10 KiB
Vue

<template>
<div id="app-container" class="p-3">
<el-row :gutter="10">
<el-col :span="1.5">
<el-button @click="handleAdd" type="primary" size="small" icon="plus"
>新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
icon="delete"
@click="handleDelete()"
type="danger"
size="small"
:disabled="multiple"
>批量删除
</el-button>
</el-col>
</el-row>
<el-table
class="short-link-table"
:data="shortLinkList"
@selection-change="handleSelectionChange"
v-loading
>
<el-table-column align="center" type="selection" width="50" />
<el-table-column
align="center"
label="名称"
prop="name"
width="120"
></el-table-column>
<el-table-column align="center" label="短链接网址" prop="jumpUrl">
<template #default="{ row }">
<el-row :gutter="5">
<el-col :span="18">
<div>
<a
class="short-link"
:href="`${row.urlPrefix}/dlj/${row.urlSuffix}`"
>
{{ row.urlPrefix }}/dlj/{{ row.urlSuffix }}
</a>
</div>
<div class="jump-url">{{ row.jumpUrl }}</div>
</el-col>
<el-col :span="6">
<el-row :gutter="5">
<el-col :span="1.5">
<i
class="iconfont icon-qrcode"
:style="{
cursor: 'pointer',
}"
@click="handleShowQrCode(row)"
></i>
</el-col>
<el-col :span="1.5">
<el-icon
:style="{
cursor: 'pointer',
}"
@click="copyToClipboard(row)"
>
<CopyDocument />
</el-icon>
</el-col>
</el-row>
</el-col>
</el-row>
</template>
</el-table-column>
<el-table-column label="访问次数" width="160" align="center">
<template #default="{ row }">
<div class="visit-count">
<div>
<span class="title">今日</span>
<span class="count">{{ row.todayVisit }}</span>
</div>
<div>
<span class="title">累计</span>
<span class="count">{{ row.historyVisit }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column
align="center"
label="过期时间"
prop="validityTime"
></el-table-column>
<el-table-column align="center" label="操作">
<template #default="{ row }">
<el-button
@click="handleUpdate(row.id)"
link
size="small"
type="warning"
>编辑
</el-button>
<el-button
@click="handleDelete(row.id)"
link
size="small"
type="danger"
>删除
</el-button>
<el-button
@click="goLogList(row.urlSuffix)"
link
size="small"
type="primary"
>访问记录
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
layout="prev, pager, next"
:page-size="queryParams.pageSize"
:current-page="queryParams.pageNum"
@update:current-page="handleCurrentChange"
:total="total"
/>
</div>
<el-dialog v-model="showEditDialog" title="新增短链接">
<el-form :model="form" ref="formRef" :rules="rules" :label-width="100">
<el-form-item label="链接标题" prop="name">
<el-input placeholder="请输入链接标题" v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="跳转链接" prop="jumpUrl">
<el-input
placeholder="请输入跳转链接"
v-model="form.jumpUrl"
></el-input>
</el-form-item>
<el-form-item label="URL前缀" prop="urlPrefix">
<el-input
placeholder="请输入URL前缀"
v-model="form.urlPrefix"
></el-input>
</el-form-item>
<el-form-item label="有效期" prop="validityTime">
<el-date-picker
value-format="YYYY-MM-DD HH:mm:ss"
v-model="form.validityTime"
type="datetime"
placeholder="请选择过期时间"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="showEditDialog = false"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="showQrCodeDialog" width="320">
<qrcode-vue
class="qrcode-canvas"
:value="qrcodeValue"
:size="280"
ref="qrcodeRef"
:margin="1"
></qrcode-vue>
<el-button
type="primary"
@click="downloadQrCode"
:style="{
width: '100%',
marginTop: '10px',
}"
>下载二维码
</el-button>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="GenShortLink">
import {
addShortLink,
deleteShortLink,
getDetailById,
listShortLink,
updateShortLink,
} from "@/api/shortlink";
import { reactive, ref, toRefs } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import type { ShortLink } from "@/models/shortLink";
import QrcodeVue from "qrcode.vue";
import { useRouter } from "vue-router";
const qrcodeRef = ref();
const shortLinkList = ref<ShortLink[]>([]);
const showEditDialog = ref(false);
const editDialogTitle = ref<string>("");
const showQrCodeDialog = ref(false);
const qrcodeValue = ref("");
const qrcodeFileName = ref("");
const formRef = ref();
const data = reactive<{
queryParams: { pageNum: number; pageSize: number };
form: ShortLink;
rules: any;
}>({
queryParams: {
pageNum: 1,
pageSize: 10,
},
form: {},
rules: {
name: [
{
required: true,
message: "请输入短链接名称",
trigger: "blur",
},
],
jumpUrl: [
{
required: true,
message: "请输入短链接",
trigger: "blur",
},
],
urlPrefix: [
{
required: true,
message: "请输入URL前缀",
trigger: "blur",
},
],
validityTime: [
{
required: true,
message: "请选择过期时间",
trigger: "change",
},
],
},
});
const { form, queryParams, rules } = toRefs(data);
const total = ref<number>(0);
const router = useRouter();
const getList = async () => {
const resp = await listShortLink(queryParams.value);
shortLinkList.value = resp.data.rows;
total.value = resp.data.total;
};
const handleShowQrCode = (data: ShortLink) => {
qrcodeValue.value = `${data.urlPrefix}/dlj/${data.urlSuffix}`;
qrcodeFileName.value = `${data.urlSuffix}.png`;
showQrCodeDialog.value = true;
};
const goLogList = (suffix: string) => {
router.push({
path: `/log-list/${suffix}`,
});
};
const reset = () => {
form.value = {
urlPrefix: "https://chuhuankj.com",
};
if (formRef.value) {
formRef.value.resetFields();
}
};
// 多选框选中数据
const linkIds = ref<number[]>([]);
const multiple = ref(true);
const single = ref(true);
const downloadQrCode = () => {
console.log(qrcodeRef.value);
const qrcodeCanvas: HTMLCanvasElement | null =
document.querySelector(".qrcode-canvas");
qrcodeCanvas?.toBlob((blob: Blob | null) => {
if (blob != null) {
let aLink = document.createElement("a");
aLink.download = qrcodeFileName.value;
aLink.href = URL.createObjectURL(blob);
aLink.click();
} else {
ElMessage.error("下载二维码失败");
}
});
};
const handleSelectionChange = (selection: ShortLink[]) => {
linkIds.value = selection.map((item: ShortLink) => item.id!);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
const copyToClipboard = (data: ShortLink) => {
navigator.clipboard.writeText(`${data.urlPrefix}/dlj/${data.urlSuffix}`);
ElMessage.success("短链接已拷贝到剪贴板");
};
const handleAdd = () => {
reset();
editDialogTitle.value = "新增短链接";
showEditDialog.value = true;
};
const handleUpdate = async (id: number) => {
reset();
const { data } = await getDetailById(id);
form.value = data.data;
editDialogTitle.value = "修改短链接";
showEditDialog.value = true;
};
const handleDelete = (id?: string) => {
let ids: string;
if (id) {
ids = id;
} else {
ids = linkIds.value.join(",");
}
ElMessageBox.confirm("确认删除该短链接吗", "删除短链接", {
type: "warning",
}).then(async () => {
await deleteShortLink(ids);
ElMessage.success("删除短链接成功");
getList();
});
};
const submitForm = async () => {
if (form.value.id) {
await updateShortLink(form.value);
ElMessage.success("短链接修改成功");
showEditDialog.value = false;
getList();
} else {
await addShortLink(form.value);
ElMessage.success("短链接添加成功");
showEditDialog.value = false;
getList();
}
};
const handleCurrentChange = (page: number) => {
queryParams.value.pageNum = page;
getList();
};
getList();
</script>
<style scoped lang="scss">
#app-container {
padding: 20px;
a.short-link {
//overflow: hidden;
//text-overflow: ellipsis;
//white-space: nowrap;
}
.jump-url {
margin-top: 5px;
font-size: 12px;
//width: 80%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.visit-count {
display: flex;
flex-direction: column;
padding: 0 20px;
& > div {
width: 100%;
display: flex;
justify-content: space-between;
}
}
.short-link-table {
margin-top: 20px;
}
.pagination {
margin-top: 20px;
margin-right: 10px;
display: flex;
justify-content: flex-end;
}
}
</style>