mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-11-12 20:23:52 +08:00
发布v2.13.1版本,更新内容请查看:https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-update-log.md
This commit is contained in:
42
web/src/views/addons/hgexample/comp/calendar/index.vue
Normal file
42
web/src/views/addons/hgexample/comp/calendar/index.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="日历"> 一个普通的日历 </n-card>
|
||||
</div>
|
||||
<n-card :bordered="false" class="mt-4 proCard">
|
||||
<n-calendar
|
||||
v-model:value="value"
|
||||
#="{ year, month, date }"
|
||||
:is-date-disabled="isDateDisabled"
|
||||
@update:value="handleUpdateValue"
|
||||
>
|
||||
{{ year }}-{{ month }}-{{ date }}
|
||||
</n-calendar>
|
||||
</n-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { isYesterday, addDays } from 'date-fns/esm';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const message = useMessage();
|
||||
return {
|
||||
value: ref(addDays(Date.now(), 1).valueOf()),
|
||||
handleUpdateValue(
|
||||
_: number,
|
||||
{ year, month, date }: { year: number; month: number; date: number }
|
||||
) {
|
||||
message.success(`${year}-${month}-${date}`);
|
||||
},
|
||||
isDateDisabled(timestamp: number) {
|
||||
if (isYesterday(timestamp)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
89
web/src/views/addons/hgexample/comp/des/index.vue
Normal file
89
web/src/views/addons/hgexample/comp/des/index.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<n-space vertical>
|
||||
<n-card>
|
||||
<template #header>基础用法</template>
|
||||
<n-descriptions label-placement="top" title="描述">
|
||||
<n-descriptions-item>
|
||||
<template #label> 早餐 </template>
|
||||
苹果
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="早午餐"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="午餐"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="晚餐" :span="2">
|
||||
两个<br />
|
||||
苹果
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="夜宵"> 苹果 </n-descriptions-item>
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
<n-card>
|
||||
<template #header>每个描述项都可以设定跨度</template>
|
||||
<n-descriptions label-placement="top" bordered :column="6">
|
||||
<n-descriptions-item>
|
||||
<template #label> 早餐 </template>
|
||||
苹果
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="早午餐"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="午餐"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="晚餐"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="正餐"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="夜宵"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="苹果"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="苹果" :span="2"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="苹果" :span="3"> 苹果 </n-descriptions-item>
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
<n-card>
|
||||
<template #header>边框</template>
|
||||
<template #header-extra> 如果有很多多行的信息,你可以把它设为 bordered </template>
|
||||
<n-descriptions bordered>
|
||||
<n-descriptions-item>
|
||||
<template #label> 早餐 </template>
|
||||
苹果
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="午餐"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="晚餐"> 苹果 </n-descriptions-item>
|
||||
<n-descriptions-item label="为什么长">
|
||||
为什么<br />长<br />长<br />长<br />长<br />长
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="为什么长">
|
||||
为什么<br />长<br />长<br />长<br />长<br />长
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="为什么长">
|
||||
为什么<br />长<br />长<br />长<br />长<br />长
|
||||
</n-descriptions-item>
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
<n-card>
|
||||
<n-list hoverable clickable>
|
||||
<n-list-item>
|
||||
<n-thing title="相见恨晚" content-style="margin-top: 10px;">
|
||||
<template #description>
|
||||
<n-space size="small" style="margin-top: 4px">
|
||||
<n-tag :bordered="false" type="info" size="small"> 暑夜 </n-tag>
|
||||
<n-tag :bordered="false" type="info" size="small"> 晚春 </n-tag>
|
||||
</n-space>
|
||||
</template>
|
||||
奋勇呀然后休息呀<br />
|
||||
完成你伟大的人生
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
<n-list-item>
|
||||
<n-thing title="他在时间门外" content-style="margin-top: 10px;">
|
||||
<template #description>
|
||||
<n-space size="small" style="margin-top: 4px">
|
||||
<n-tag :bordered="false" type="info" size="small"> 环形公路 </n-tag>
|
||||
<n-tag :bordered="false" type="info" size="small"> 潜水艇司机 </n-tag>
|
||||
</n-space>
|
||||
</template>
|
||||
最新的打印机<br />
|
||||
复制着彩色傀儡<br />
|
||||
早上好<br />
|
||||
让他带你去被工厂敲击
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</template>
|
||||
<script setup></script>
|
||||
58
web/src/views/addons/hgexample/comp/directive/index.vue
Normal file
58
web/src/views/addons/hgexample/comp/directive/index.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="card content-box">
|
||||
<n-card :bordered="false" title="复制指令">
|
||||
<n-space>
|
||||
<n-input placeholder="输入内容试试" v-model:value="data" style="width: 350px" />
|
||||
<n-button v-copy="data" type="primary" @click="a">复 制</n-button>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card :bordered="false" title="防抖指令" class="mt-3">
|
||||
<n-button type="primary" v-debounce="b">防抖测试</n-button>
|
||||
</n-card>
|
||||
<n-card :bordered="false" title="节流指令" class="mt-3">
|
||||
<n-button type="primary" v-throttle="c">节流测试</n-button>
|
||||
</n-card>
|
||||
|
||||
<n-card :bordered="false" title="拖拽指令" class="mt-3"> 鼠标放到矩形上面拖拽试试 </n-card>
|
||||
<div class="box" v-draggable> </div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="copyDirect">
|
||||
import { ref } from 'vue';
|
||||
import { useMessage } from 'naive-ui';
|
||||
const data = ref<string>();
|
||||
const message = useMessage();
|
||||
const a = () => {
|
||||
message.success('复制成功:' + data.value);
|
||||
};
|
||||
const b = () => {
|
||||
message.success('防抖');
|
||||
console.log(data.value);
|
||||
};
|
||||
const c = () => {
|
||||
message.success('节流');
|
||||
console.log(data.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
body {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: #ccc;
|
||||
position: relative;
|
||||
}
|
||||
.content-box {
|
||||
height: 100vh;
|
||||
.box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: #2d8cf0;
|
||||
position: absolute;
|
||||
z-index: 10000000;
|
||||
border-radius: 10px;
|
||||
margin: 20px 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
162
web/src/views/addons/hgexample/comp/drag/index.vue
Normal file
162
web/src/views/addons/hgexample/comp/drag/index.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="拖拽"> 常用于卡片,事项,预约,流程,计划等, </n-card>
|
||||
</div>
|
||||
|
||||
<n-alert title="花式拖拽演示" type="info" class="mt-4">
|
||||
每个卡片,都可以上下拖拽顺序,另外不同卡片,也可以拖拽过去,拖拽过来,都不在话下呢,快试试O(∩_∩)O哈哈~
|
||||
</n-alert>
|
||||
|
||||
<n-grid
|
||||
cols="1 s:2 m:3 l:4 xl:4 2xl:4"
|
||||
class="mt-4 proCard"
|
||||
responsive="screen"
|
||||
:x-gap="12"
|
||||
:y-gap="8"
|
||||
>
|
||||
<n-grid-item>
|
||||
<NCard
|
||||
title="需求池"
|
||||
:segmented="{ content: true, footer: true }"
|
||||
size="small"
|
||||
:bordered="false"
|
||||
>
|
||||
<template #header-extra>
|
||||
<n-tag type="info">月</n-tag>
|
||||
</template>
|
||||
|
||||
<Draggable
|
||||
class="draggable-ul"
|
||||
animation="300"
|
||||
:list="demandList"
|
||||
group="people"
|
||||
itemKey="name"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div class="cursor-move draggable-li">
|
||||
<n-tag type="info">需求</n-tag><span class="ml-2">{{ element.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</Draggable>
|
||||
</NCard>
|
||||
</n-grid-item>
|
||||
|
||||
<n-grid-item>
|
||||
<NCard
|
||||
title="开发中"
|
||||
:segmented="{ content: true, footer: true }"
|
||||
size="small"
|
||||
:bordered="false"
|
||||
>
|
||||
<template #header-extra>
|
||||
<n-tag type="info">月</n-tag>
|
||||
</template>
|
||||
|
||||
<Draggable
|
||||
class="draggable-ul"
|
||||
animation="300"
|
||||
:list="exploitList"
|
||||
group="people"
|
||||
itemKey="name"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div class="cursor-move draggable-li">
|
||||
<n-tag type="warning">开发中</n-tag><span class="ml-2">{{ element.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</Draggable>
|
||||
</NCard>
|
||||
</n-grid-item>
|
||||
|
||||
<n-grid-item>
|
||||
<NCard
|
||||
title="已完成"
|
||||
:segmented="{ content: true, footer: true }"
|
||||
size="small"
|
||||
:bordered="false"
|
||||
>
|
||||
<template #header-extra>
|
||||
<n-tag type="info">月</n-tag>
|
||||
</template>
|
||||
<Draggable
|
||||
class="draggable-ul"
|
||||
animation="300"
|
||||
:list="completeList"
|
||||
group="people"
|
||||
itemKey="name"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div class="cursor-move draggable-li">
|
||||
<n-tag type="error">已完成</n-tag><span class="ml-2">{{ element.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</Draggable>
|
||||
</NCard>
|
||||
</n-grid-item>
|
||||
|
||||
<n-grid-item>
|
||||
<NCard
|
||||
title="已验收"
|
||||
:segmented="{ content: true, footer: true }"
|
||||
size="small"
|
||||
:bordered="false"
|
||||
>
|
||||
<template #header-extra>
|
||||
<n-tag type="info">月</n-tag>
|
||||
</template>
|
||||
<Draggable
|
||||
class="draggable-ul"
|
||||
animation="300"
|
||||
:list="approvedList"
|
||||
group="people"
|
||||
itemKey="name"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div class="cursor-move draggable-li">
|
||||
<n-tag type="success">已验收</n-tag><span class="ml-2">{{ element.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</Draggable>
|
||||
</NCard>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import Draggable from 'vuedraggable';
|
||||
|
||||
const demandList = reactive([
|
||||
{ name: '预约表单页面,能填写预约相关信息', id: 1 },
|
||||
{ name: '促销活动页面,包含促销广告展示', id: 2 },
|
||||
{ name: '商品列表,需要一个到货提醒功能', id: 3 },
|
||||
{ name: '商品需要一个评价功能', id: 4 },
|
||||
{ name: '商品图片需要提供放大镜', id: 5 },
|
||||
{ name: '订单需要提供删除到回收站', id: 6 },
|
||||
{ name: '用户头像上传,需要支持裁剪', id: 7 },
|
||||
{ name: '据说Vue3.2发布了,setup啥时候支持?', id: 8 },
|
||||
]);
|
||||
|
||||
const exploitList = reactive([{ name: '商品图片需要提供放大镜', id: 5 }]);
|
||||
|
||||
const completeList = reactive([{ name: '商品图片需要提供放大镜', id: 5 }]);
|
||||
|
||||
const approvedList = reactive([{ name: '商品图片需要提供放大镜', id: 5 }]);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.draggable-ul {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
margin-top: -16px;
|
||||
|
||||
.draggable-li {
|
||||
width: 100%;
|
||||
padding: 16px 10px;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #efeff5;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
38
web/src/views/addons/hgexample/comp/fingerprintjs/index.vue
Normal file
38
web/src/views/addons/hgexample/comp/fingerprintjs/index.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<n-card :segmented="{ content: true, footer: true }" footer-style="padding:10px">
|
||||
<template #header>
|
||||
通过设备浏览器信息获取浏览器指纹的插件(官方宣称其识别精度达到99.5%)
|
||||
</template>
|
||||
<div>
|
||||
指纹ID:
|
||||
<n-text type="info">
|
||||
{{ compData.murmur }}
|
||||
</n-text>
|
||||
</div>
|
||||
</n-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import Fingerprint2 from 'fingerprintjs2';
|
||||
|
||||
const compData = reactive({
|
||||
values: {},
|
||||
murmur: '',
|
||||
});
|
||||
|
||||
const createFingerprint = () => {
|
||||
Fingerprint2.get((components) => {
|
||||
compData.values = components.map((component) => component.value); // 配置的值的数组
|
||||
compData.murmur = Fingerprint2.x64hash128(compData.values.join(''), 31).toUpperCase(); // 生成浏览器指纹
|
||||
});
|
||||
};
|
||||
if (window.requestIdleCallback) {
|
||||
requestIdleCallback(() => {
|
||||
createFingerprint();
|
||||
});
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
createFingerprint();
|
||||
}, 600);
|
||||
}
|
||||
</script>
|
||||
175
web/src/views/addons/hgexample/comp/form/basic.vue
Normal file
175
web/src/views/addons/hgexample/comp/form/basic.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="基础表单"> 基础表单,用于向用户收集表单信息 </n-card>
|
||||
</div>
|
||||
<n-card :bordered="false" class="mt-4 proCard">
|
||||
<div class="BasicForm">
|
||||
<BasicForm
|
||||
submitButtonText="提交预约"
|
||||
layout="horizontal"
|
||||
:gridProps="{ cols: 1 }"
|
||||
:schemas="schemas"
|
||||
@submit="handleSubmit"
|
||||
@reset="handleReset"
|
||||
>
|
||||
<template #statusSlot="{ model, field }">
|
||||
<n-input v-model:value="model[field]" />
|
||||
</template>
|
||||
</BasicForm>
|
||||
</div>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { BasicForm, FormSchema } from '@/components/Form/index';
|
||||
import { useMessage } from 'naive-ui';
|
||||
|
||||
const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
component: 'NInput',
|
||||
label: '姓名',
|
||||
labelMessage: '这是一个提示',
|
||||
componentProps: {
|
||||
placeholder: '请输入姓名',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
rules: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
|
||||
},
|
||||
{
|
||||
field: 'mobile',
|
||||
component: 'NInputNumber',
|
||||
label: '手机',
|
||||
componentProps: {
|
||||
placeholder: '请输入手机号码',
|
||||
showButton: false,
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'type',
|
||||
component: 'NSelect',
|
||||
label: '类型',
|
||||
componentProps: {
|
||||
placeholder: '请选择类型',
|
||||
options: [
|
||||
{
|
||||
label: '舒适性',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '经济性',
|
||||
value: 2,
|
||||
},
|
||||
],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeDate',
|
||||
component: 'NDatePicker',
|
||||
label: '预约时间',
|
||||
defaultValue: 1183135260000,
|
||||
componentProps: {
|
||||
type: 'date',
|
||||
clearable: true,
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeTime',
|
||||
component: 'NTimePicker',
|
||||
label: '停留时间',
|
||||
componentProps: {
|
||||
clearable: true,
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeProject',
|
||||
component: 'NCheckbox',
|
||||
label: '预约项目',
|
||||
componentProps: {
|
||||
placeholder: '请选择预约项目',
|
||||
options: [
|
||||
{
|
||||
label: '种牙',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '补牙',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '根管',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
onUpdateChecked: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeSource',
|
||||
component: 'NRadioGroup',
|
||||
label: '来源',
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '网上',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '门店',
|
||||
value: 2,
|
||||
},
|
||||
],
|
||||
onUpdateChecked: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
label: '状态',
|
||||
//插槽
|
||||
slot: 'statusSlot',
|
||||
},
|
||||
];
|
||||
|
||||
const message = useMessage();
|
||||
|
||||
function handleSubmit(values: Recordable) {
|
||||
if (!values) {
|
||||
return message.error('请填写完整信息');
|
||||
}
|
||||
console.log(values);
|
||||
message.success(JSON.stringify(values));
|
||||
}
|
||||
|
||||
function handleReset(values: Recordable) {
|
||||
console.log(values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.BasicForm {
|
||||
width: 550px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
padding-top: 20px;
|
||||
}
|
||||
</style>
|
||||
198
web/src/views/addons/hgexample/comp/form/useForm.vue
Normal file
198
web/src/views/addons/hgexample/comp/form/useForm.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="基础表单"> useForm 表单,用于向用户收集表单信息 </n-card>
|
||||
</div>
|
||||
<n-card :bordered="false" class="mt-4 proCard">
|
||||
<div class="BasicForm">
|
||||
<BasicForm @register="register" @submit="handleSubmit" @reset="handleReset">
|
||||
<template #statusSlot="{ model, field }">
|
||||
<n-input v-model:value="model[field]" />
|
||||
</template>
|
||||
</BasicForm>
|
||||
</div>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
|
||||
import { useMessage } from 'naive-ui';
|
||||
|
||||
const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
component: 'NInput',
|
||||
label: '姓名',
|
||||
labelMessage: '这是一个提示',
|
||||
giProps: {
|
||||
span: 1,
|
||||
},
|
||||
componentProps: {
|
||||
placeholder: '请输入姓名',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
rules: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
|
||||
},
|
||||
{
|
||||
field: 'mobile',
|
||||
component: 'NInputNumber',
|
||||
label: '手机',
|
||||
componentProps: {
|
||||
placeholder: '请输入手机号码',
|
||||
showButton: false,
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'type',
|
||||
component: 'NSelect',
|
||||
label: '类型',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
componentProps: {
|
||||
placeholder: '请选择类型',
|
||||
options: [
|
||||
{
|
||||
label: '舒适性',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '经济性',
|
||||
value: 2,
|
||||
},
|
||||
],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeDate',
|
||||
component: 'NDatePicker',
|
||||
label: '预约时间',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
defaultValue: 1183135260000,
|
||||
componentProps: {
|
||||
type: 'date',
|
||||
clearable: true,
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeTime',
|
||||
component: 'NTimePicker',
|
||||
label: '停留时间',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
componentProps: {
|
||||
clearable: true,
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeProject',
|
||||
component: 'NCheckbox',
|
||||
label: '预约项目',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
componentProps: {
|
||||
placeholder: '请选择预约项目',
|
||||
options: [
|
||||
{
|
||||
label: '种牙',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '补牙',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '根管',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
onUpdateChecked: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeSource',
|
||||
component: 'NRadioGroup',
|
||||
label: '来源',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '网上',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '门店',
|
||||
value: 2,
|
||||
},
|
||||
],
|
||||
onUpdateChecked: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
label: '状态',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
//插槽
|
||||
slot: 'statusSlot',
|
||||
},
|
||||
];
|
||||
|
||||
const message = useMessage();
|
||||
|
||||
const [register, {}] = useForm({
|
||||
gridProps: { cols: 1 },
|
||||
collapsedRows: 3,
|
||||
labelWidth: 120,
|
||||
layout: 'horizontal',
|
||||
submitButtonText: '提交预约',
|
||||
schemas,
|
||||
});
|
||||
|
||||
function handleSubmit(values: Recordable) {
|
||||
if (!values) {
|
||||
return message.error('请填写完整信息');
|
||||
}
|
||||
console.log(values);
|
||||
message.success(JSON.stringify(values));
|
||||
}
|
||||
|
||||
function handleReset(values: Recordable) {
|
||||
console.log(values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.BasicForm {
|
||||
width: 550px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
padding-top: 20px;
|
||||
}
|
||||
</style>
|
||||
23
web/src/views/addons/hgexample/comp/icons/antd.vue
Normal file
23
web/src/views/addons/hgexample/comp/icons/antd.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-spin :show="loading" description="请稍候..">
|
||||
<Icons ref="iconsRef" />
|
||||
</n-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import Icons from './icons.vue';
|
||||
|
||||
const iconsRef = ref();
|
||||
const loading = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
iconsRef.value?.open('antd');
|
||||
loading.value = false;
|
||||
}, 10);
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
136
web/src/views/addons/hgexample/comp/icons/icons.vue
Normal file
136
web/src/views/addons/hgexample/comp/icons/icons.vue
Normal file
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
content-style=""
|
||||
>
|
||||
<template #header>
|
||||
<n-grid y-gap="20" x-gap="10" cols="24" item-responsive responsive="screen">
|
||||
<n-grid-item span="24 m:12 l:6">
|
||||
<n-input-group>
|
||||
<n-button>图标大小</n-button>
|
||||
<n-input-number style="width: 100%" v-model:value="compData.size" />
|
||||
</n-input-group>
|
||||
</n-grid-item>
|
||||
<n-grid-item span="24 m:12 l:6">
|
||||
<n-color-picker
|
||||
:modes="['hex']"
|
||||
style="width: 100%"
|
||||
v-model:value="compData.color"
|
||||
:swatches="['#FFFFFF', '#18A058', '#2080F0', '#F0A020', '#D03050','#000000']"
|
||||
>
|
||||
<template #label>
|
||||
<div style="color: white">图标颜色 {{ compData.color }}</div>
|
||||
</template>
|
||||
</n-color-picker>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
</template>
|
||||
<div class="icons">
|
||||
<n-grid y-gap="20" x-gap="0" cols="24" item-responsive responsive="screen">
|
||||
<n-grid-item v-for="(item, idx) in icons" :key="idx" span="12 m:4 l:3 xl:2">
|
||||
<div class="icons-item">
|
||||
<div class="icons-item_content">
|
||||
<n-icon class="icon" :color="compData.color" :size="compData.size">
|
||||
<component :is="item" />
|
||||
</n-icon>
|
||||
<span class="copy" v-copy="item.name" @click="handleCopy(item)">复制</span>
|
||||
</div>
|
||||
</div>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
</div>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import * as AntdIcons from '@vicons/antd';
|
||||
import * as Ionicons5 from '@vicons/ionicons5';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { useDesignSettingStore } from '@/store/modules/designSetting';
|
||||
|
||||
const designStore = useDesignSettingStore();
|
||||
const message = useMessage();
|
||||
|
||||
const icons = ref<any>([]);
|
||||
const compData = ref({
|
||||
color: designStore.appTheme,
|
||||
size: 32,
|
||||
});
|
||||
|
||||
const color = computed(() => {
|
||||
return compData.value.color;
|
||||
});
|
||||
|
||||
function handleCopy(icon) {
|
||||
message.success(`已复制,${icon.name}`);
|
||||
}
|
||||
|
||||
function open(type: string) {
|
||||
if (type === 'antd') {
|
||||
icons.value = AntdIcons;
|
||||
}
|
||||
if (type === 'ionicons5') {
|
||||
icons.value = Ionicons5;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
:deep(.n-color-picker-trigger .n-color-picker-trigger__fill) {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.icons {
|
||||
&-item {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 0 10px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
&_content {
|
||||
padding: 20px 10px;
|
||||
border: 1px solid rgb(240 240 245);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.icon {
|
||||
transition: top 0.3s;
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
&:hover {
|
||||
.icon {
|
||||
top: -10px;
|
||||
}
|
||||
.copy {
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
.copy {
|
||||
position: absolute;
|
||||
bottom: -30px;
|
||||
height: 30px;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
line-height: 30px;
|
||||
background-color: v-bind(color);
|
||||
transition: bottom 0.3s;
|
||||
color: rgb(240 240 245);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
23
web/src/views/addons/hgexample/comp/icons/ionicons5.vue
Normal file
23
web/src/views/addons/hgexample/comp/icons/ionicons5.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-spin :show="loading" description="请稍候..">
|
||||
<Icons ref="iconsRef" />
|
||||
</n-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import Icons from './icons.vue';
|
||||
|
||||
const iconsRef = ref();
|
||||
const loading = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
iconsRef.value?.open('ionicons5');
|
||||
loading.value = false;
|
||||
}, 10);
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
29
web/src/views/addons/hgexample/comp/icons/selector.vue
Normal file
29
web/src/views/addons/hgexample/comp/icons/selector.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="图标选择器">
|
||||
图标选择器,用于表单选择图标,支持直接选定图标和输入图标名称来选择
|
||||
</n-card>
|
||||
</div>
|
||||
<n-space>
|
||||
<n-card :bordered="false" class="mt-4 proCard" title="Antd">
|
||||
<IconSelector style="width: 100%" v-model:value="antdValue" option="antd" />
|
||||
</n-card>
|
||||
|
||||
<n-card :bordered="false" class="mt-4 proCard" title="Ionicons5">
|
||||
<IconSelector style="width: 100%" v-model:value="ionicons5Value" option="ionicons5" />
|
||||
</n-card>
|
||||
</n-space>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import IconSelector from '@/components/IconSelector/index.vue';
|
||||
|
||||
const antdValue = ref('');
|
||||
const ionicons5Value = ref('');
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
68
web/src/views/addons/hgexample/comp/import/excel.vue
Normal file
68
web/src/views/addons/hgexample/comp/import/excel.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="导入excel">
|
||||
将excel表格数据导入,可解析出完整的表格内容,包括所有的sheet和行列数据
|
||||
</n-card>
|
||||
</div>
|
||||
<n-card :bordered="false" class="mt-4 proCard">
|
||||
<n-upload
|
||||
directory-dnd
|
||||
:custom-request="handleUpload"
|
||||
name="file"
|
||||
type="file"
|
||||
accept=".xlsx, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
>
|
||||
<n-upload-dragger>
|
||||
<div style="margin-bottom: 12px">
|
||||
<n-icon size="48" :depth="3">
|
||||
<DownloadOutlined />
|
||||
</n-icon>
|
||||
</div>
|
||||
<n-text style="font-size: 16px"> 点击或者拖动.xlsx文件到该区域来上传</n-text>
|
||||
<n-p depth="3" style="margin: 8px 0 0 0"> 单次上传数据最大不建议超过5000条</n-p>
|
||||
</n-upload-dragger>
|
||||
</n-upload>
|
||||
</n-card>
|
||||
|
||||
<n-card
|
||||
:bordered="false"
|
||||
class="proCard mt-4"
|
||||
size="small"
|
||||
:segmented="{ content: true }"
|
||||
title="表格数据"
|
||||
>
|
||||
<n-scrollbar style="max-height: 520px">
|
||||
<JsonViewer :value="response" :expand-depth="5" copyable boxed sort class="json-width" />
|
||||
</n-scrollbar>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { UploadCustomRequestOptions, useMessage } from 'naive-ui';
|
||||
import { DownloadOutlined } from '@vicons/antd';
|
||||
import { ImportExcel } from '@/api/addons/hgexample/comp';
|
||||
import type { UploadFileParams } from '@/utils/http/axios/types';
|
||||
import { JsonViewer } from 'vue3-json-viewer';
|
||||
import 'vue3-json-viewer/dist/index.css';
|
||||
|
||||
const message = useMessage();
|
||||
const response = ref<any>({});
|
||||
|
||||
function handleUpload(options: UploadCustomRequestOptions) {
|
||||
message.loading('正在导入,请稍候...', { duration: 1200 });
|
||||
const params: UploadFileParams = {
|
||||
file: options.file.file as File,
|
||||
};
|
||||
|
||||
ImportExcel(params).then((res) => {
|
||||
response.value = res;
|
||||
message.destroyAll();
|
||||
message.success('解析成功');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less"></style>
|
||||
369
web/src/views/addons/hgexample/comp/index.vue
Normal file
369
web/src/views/addons/hgexample/comp/index.vue
Normal file
@@ -0,0 +1,369 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-card :bordered="false" class="proCard">
|
||||
<n-p class="title">组件示例</n-p>
|
||||
<n-space vertical>
|
||||
<n-layout has-sider>
|
||||
<n-scrollbar :style="scrollbarStyle">
|
||||
<n-layout-sider
|
||||
bordered
|
||||
collapse-mode="width"
|
||||
:collapsed-width="64"
|
||||
:width="180"
|
||||
:collapsed="collapsed"
|
||||
show-trigger
|
||||
@collapse="collapsed = true"
|
||||
@expand="collapsed = false"
|
||||
>
|
||||
<n-menu
|
||||
v-model:value="activeKey"
|
||||
:collapsed="collapsed"
|
||||
:collapsed-width="64"
|
||||
:collapsed-icon-size="22"
|
||||
:options="menuOptions"
|
||||
/>
|
||||
</n-layout-sider>
|
||||
</n-scrollbar>
|
||||
|
||||
<n-layout>
|
||||
<n-card :bordered="false" class="proCard">
|
||||
<component :is="currentComponent" />
|
||||
</n-card>
|
||||
</n-layout>
|
||||
</n-layout>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import type { MenuOption } from 'naive-ui';
|
||||
import {
|
||||
ProfileOutlined,
|
||||
BorderOutlined,
|
||||
NumberOutlined,
|
||||
BorderOuterOutlined,
|
||||
CheckCircleOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
FundProjectionScreenOutlined,
|
||||
ReadOutlined,
|
||||
StarOutlined,
|
||||
PushpinOutlined,
|
||||
LayoutOutlined,
|
||||
PrinterOutlined,
|
||||
DownloadOutlined,
|
||||
} from '@vicons/antd';
|
||||
import {
|
||||
HourglassOutline,
|
||||
NotificationsOutline,
|
||||
LocationOutline,
|
||||
SwapVertical,
|
||||
EllipsisHorizontalCircleOutline,
|
||||
AlbumsOutline,
|
||||
LogoChrome,
|
||||
} from '@vicons/ionicons5';
|
||||
import { renderIcon } from '@/utils';
|
||||
import FormBasic from './form/basic.vue';
|
||||
import FormUseForm from './form/useForm.vue';
|
||||
import Modal from './modal/index.vue';
|
||||
import Drag from './drag/index.vue';
|
||||
import Directive from './directive/index.vue';
|
||||
import ResultSuccess from './result/success.vue';
|
||||
import ResultFail from './result/fail.vue';
|
||||
import ResultInfo from './result/info.vue';
|
||||
import Exception403 from '../../../exception/403.vue';
|
||||
import Exception404 from '../../../exception/404.vue';
|
||||
import Exception500 from '../../../exception/500.vue';
|
||||
import VisPPchart from './vis/ppchart.vue';
|
||||
import VisEcharts from './vis/echarts.vue';
|
||||
import VisMadeAPie from './vis/madeapie.vue';
|
||||
import TextPinyin from './text/pinyin/index.vue';
|
||||
import TextMint from './text/mint/index.vue';
|
||||
import TextGradient from './text/gradient/index.vue';
|
||||
import TextHigh from './text/high/index.vue';
|
||||
import IconsAntd from './icons/antd.vue';
|
||||
import IconsIonicons5 from './icons/ionicons5.vue';
|
||||
import IconsSelector from './icons/selector.vue';
|
||||
import Watermark from './watermark/index.vue';
|
||||
import Des from './des/index.vue';
|
||||
import Calendar from './calendar/index.vue';
|
||||
import Timeline from './timeline/index.vue';
|
||||
import Notice from './notice/index.vue';
|
||||
import MapGaode from './map/gaode.vue';
|
||||
import MapBaidu from './map/baidu.vue';
|
||||
import Print from './print/index.vue';
|
||||
import TagsView from './tagsView/index.vue';
|
||||
import MoreComponents from './moreComponents/index.vue';
|
||||
import Waterfall from './waterfall/index.vue';
|
||||
import ImportExcel from './import/excel.vue';
|
||||
import FingerPrintJs from './fingerprintjs/index.vue';
|
||||
|
||||
const components = {
|
||||
formBasic: FormBasic,
|
||||
formUseForm: FormUseForm,
|
||||
modal: Modal,
|
||||
drag: Drag,
|
||||
directive: Directive,
|
||||
resultSuccess: ResultSuccess,
|
||||
resultFail: ResultFail,
|
||||
resultInfo: ResultInfo,
|
||||
exception403: Exception403,
|
||||
exception404: Exception404,
|
||||
exception500: Exception500,
|
||||
visPPchart: VisPPchart,
|
||||
visEcharts: VisEcharts,
|
||||
visMadeAPie: VisMadeAPie,
|
||||
textPinyin: TextPinyin,
|
||||
textMint: TextMint,
|
||||
textGradient: TextGradient,
|
||||
textHigh: TextHigh,
|
||||
iconsAntd: IconsAntd,
|
||||
iconsIonicons5: IconsIonicons5,
|
||||
iconsSelector: IconsSelector,
|
||||
watermark: Watermark,
|
||||
des: Des,
|
||||
calendar: Calendar,
|
||||
timeline: Timeline,
|
||||
notice: Notice,
|
||||
mapGaode: MapGaode,
|
||||
mapBaidu: MapBaidu,
|
||||
print: Print,
|
||||
tagsView: TagsView,
|
||||
moreComponents: MoreComponents,
|
||||
waterfall: Waterfall,
|
||||
importExcel: ImportExcel,
|
||||
fingerPrintJs: FingerPrintJs,
|
||||
};
|
||||
|
||||
const activeKey = ref<string>('formBasic');
|
||||
const collapsed = ref(false);
|
||||
|
||||
const scrollbarStyle = computed(() => {
|
||||
const height = '82vh';
|
||||
const width = collapsed.value ? '74px' : '188px';
|
||||
return {
|
||||
height: height,
|
||||
'max-height': height,
|
||||
'min-width': width,
|
||||
width: width,
|
||||
};
|
||||
});
|
||||
|
||||
const currentComponent = computed(() => {
|
||||
return components[activeKey.value] || null;
|
||||
});
|
||||
|
||||
const menuOptions: MenuOption[] = [
|
||||
{
|
||||
label: '表单',
|
||||
key: 'form',
|
||||
icon: renderIcon(ProfileOutlined),
|
||||
children: [
|
||||
{
|
||||
label: '基础使用',
|
||||
key: 'formBasic',
|
||||
},
|
||||
{
|
||||
label: 'useForm',
|
||||
key: 'formUseForm',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '图标',
|
||||
key: 'icons',
|
||||
icon: renderIcon(StarOutlined),
|
||||
children: [
|
||||
{
|
||||
label: 'Antd',
|
||||
key: 'iconsAntd',
|
||||
},
|
||||
{
|
||||
label: 'IonIcons5',
|
||||
key: 'iconsIonicons5',
|
||||
},
|
||||
{
|
||||
label: '选择器',
|
||||
key: 'iconsSelector',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '文字处理',
|
||||
key: 'text',
|
||||
icon: renderIcon(ReadOutlined),
|
||||
children: [
|
||||
{
|
||||
label: '汉字拼音',
|
||||
key: 'textPinyin',
|
||||
},
|
||||
{
|
||||
label: '敏感词汇',
|
||||
key: 'textMint',
|
||||
},
|
||||
{
|
||||
label: '渐变文字',
|
||||
key: 'textGradient',
|
||||
},
|
||||
{
|
||||
label: '文字高亮',
|
||||
key: 'textHigh',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '可视化',
|
||||
key: 'vis',
|
||||
icon: renderIcon(FundProjectionScreenOutlined),
|
||||
children: [
|
||||
{
|
||||
label: 'PPChart',
|
||||
key: 'visPPchart',
|
||||
},
|
||||
{
|
||||
label: 'Echarts',
|
||||
key: 'visEcharts',
|
||||
},
|
||||
{
|
||||
label: 'MadeAPie',
|
||||
key: 'visMadeAPie',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '异常页面',
|
||||
key: 'exception',
|
||||
icon: renderIcon(ExclamationCircleOutlined),
|
||||
children: [
|
||||
{
|
||||
label: '403',
|
||||
key: 'exception403',
|
||||
},
|
||||
{
|
||||
label: '404',
|
||||
key: 'exception404',
|
||||
},
|
||||
{
|
||||
label: '500',
|
||||
key: 'exception500',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '结果页面',
|
||||
key: 'result',
|
||||
icon: renderIcon(CheckCircleOutlined),
|
||||
children: [
|
||||
{
|
||||
label: '成功页',
|
||||
key: 'resultSuccess',
|
||||
},
|
||||
{
|
||||
label: '失败页',
|
||||
key: 'resultFail',
|
||||
},
|
||||
{
|
||||
label: '信息页',
|
||||
key: 'resultInfo',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '地图',
|
||||
key: 'map',
|
||||
icon: renderIcon(LocationOutline),
|
||||
children: [
|
||||
{
|
||||
label: '高德地图',
|
||||
key: 'mapGaode',
|
||||
},
|
||||
{
|
||||
label: '百度地图',
|
||||
key: 'mapBaidu',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '弹窗扩展',
|
||||
key: 'modal',
|
||||
icon: renderIcon(BorderOutlined),
|
||||
},
|
||||
{
|
||||
label: '消息提示',
|
||||
key: 'notice',
|
||||
icon: renderIcon(NotificationsOutline),
|
||||
},
|
||||
{
|
||||
label: '瀑布流',
|
||||
key: 'waterfall',
|
||||
icon: renderIcon(AlbumsOutline),
|
||||
},
|
||||
{
|
||||
label: '拖拽',
|
||||
key: 'drag',
|
||||
icon: renderIcon(NumberOutlined),
|
||||
},
|
||||
{
|
||||
label: '水印',
|
||||
key: 'watermark',
|
||||
icon: renderIcon(PushpinOutlined),
|
||||
},
|
||||
{
|
||||
label: '日历',
|
||||
key: 'calendar',
|
||||
icon: renderIcon(ReadOutlined),
|
||||
},
|
||||
{
|
||||
label: '打印',
|
||||
key: 'print',
|
||||
icon: renderIcon(PrinterOutlined),
|
||||
},
|
||||
|
||||
{
|
||||
label: '时间线',
|
||||
key: 'timeline',
|
||||
icon: renderIcon(HourglassOutline),
|
||||
},
|
||||
{
|
||||
label: 'tagsView',
|
||||
key: 'tagsView',
|
||||
icon: renderIcon(SwapVertical),
|
||||
},
|
||||
{
|
||||
label: '导入Excel',
|
||||
key: 'importExcel',
|
||||
icon: renderIcon(DownloadOutlined),
|
||||
},
|
||||
{
|
||||
label: '卡片描述',
|
||||
key: 'des',
|
||||
icon: renderIcon(LayoutOutlined),
|
||||
},
|
||||
{
|
||||
label: '指令示例',
|
||||
key: 'directive',
|
||||
icon: renderIcon(BorderOuterOutlined),
|
||||
},
|
||||
{
|
||||
label: '浏览器指纹',
|
||||
key: 'fingerPrintJs',
|
||||
icon: renderIcon(LogoChrome),
|
||||
},
|
||||
{
|
||||
label: '更多组件',
|
||||
key: 'moreComponents',
|
||||
icon: renderIcon(EllipsisHorizontalCircleOutline),
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.title {
|
||||
font-size: 18px;
|
||||
transition: color 0.3s var(--n-bezier);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
color: var(--n-title-text-color);
|
||||
}
|
||||
</style>
|
||||
33
web/src/views/addons/hgexample/comp/map/baidu.vue
Normal file
33
web/src/views/addons/hgexample/comp/map/baidu.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<div class="container" ref="container"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import useCreateScript from '@/hooks/useCreateScript';
|
||||
|
||||
const SCRIPT_URL =
|
||||
'http://api.map.baidu.com/getscript?v=3.0&ak=WxbQmaOc3bvSGSaKWcyeFSf8fnYCWpKd&services=&t=' +
|
||||
new Date().getTime();
|
||||
const container = ref<HTMLDivElement | null>(null);
|
||||
const { createScriptPromise } = useCreateScript(SCRIPT_URL);
|
||||
const initMap = () => {
|
||||
createScriptPromise.then(() => {
|
||||
const bMap = (window as any).BMap;
|
||||
const map: any = new bMap.Map(container.value);
|
||||
const point = new bMap.Point(116.404, 39.915);
|
||||
map.centerAndZoom(point, 7);
|
||||
map.enableScrollWheelZoom();
|
||||
map.setMapStyleV2({ styleId: 'ea4652613f3629247d47666706ce7e89' });
|
||||
});
|
||||
};
|
||||
onMounted(initMap);
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 720px;
|
||||
margin-top: -32px;
|
||||
}
|
||||
</style>
|
||||
34
web/src/views/addons/hgexample/comp/map/gaode.vue
Normal file
34
web/src/views/addons/hgexample/comp/map/gaode.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div class="container" ref="container"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import useCreateScript from '@/hooks/useCreateScript';
|
||||
|
||||
const SCRIPT_URL = 'https://webapi.amap.com/maps?v=1.4.15&key=9f2d3fcc4b12a7c915fded4b55902e21';
|
||||
const container = ref<HTMLDivElement | null>(null);
|
||||
const height = ref(0);
|
||||
const { createScriptPromise } = useCreateScript(SCRIPT_URL);
|
||||
const initMap = () => {
|
||||
height.value = container.value?.parentElement?.getBoundingClientRect().height || 0;
|
||||
createScriptPromise.then(() => {
|
||||
const aMap: any = (window as any).AMap;
|
||||
new aMap.Map(container.value, {
|
||||
zoom: 22,
|
||||
center: [116.397428, 39.90923],
|
||||
viewMode: '3D',
|
||||
pitch: 75,
|
||||
});
|
||||
});
|
||||
};
|
||||
onMounted(initMap);
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 720px;
|
||||
margin-top: -32px;
|
||||
}
|
||||
</style>
|
||||
307
web/src/views/addons/hgexample/comp/modal/index.vue
Normal file
307
web/src/views/addons/hgexample/comp/modal/index.vue
Normal file
@@ -0,0 +1,307 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="模态框">
|
||||
模态框,用于向用户收集或展示信息,Modal 采用 Dialog 预设,扩展拖拽效果
|
||||
<br />
|
||||
以下是 useModal
|
||||
方式,ref方式,也支持,使用方式和其他组件一致,如:modalRef.value.closeModal()
|
||||
</n-card>
|
||||
</div>
|
||||
<n-card :bordered="false" class="mt-4 proCard">
|
||||
<n-alert title="Modal嵌套Form" type="info">
|
||||
使用 useModal 进行弹窗展示和操作,并演示了在Modal内和Form组件,组合使用方法
|
||||
</n-alert>
|
||||
<n-divider />
|
||||
<n-space>
|
||||
<n-button type="primary" @click="showModal">打开Modal嵌套Form例子</n-button>
|
||||
</n-space>
|
||||
<n-divider />
|
||||
<n-alert title="个性化轻量级" type="info">
|
||||
使用 useModal 进行弹窗展示和操作,自定义配置,实现轻量级效果,更多配置,请参考文档
|
||||
</n-alert>
|
||||
<n-divider />
|
||||
<n-space>
|
||||
<n-button type="primary" @click="showLightModal">轻量级确认</n-button>
|
||||
</n-space>
|
||||
<n-divider />
|
||||
<n-alert title="提示" type="info">
|
||||
组件暴露了,setProps 方法,用于修改组件内部
|
||||
Props,比如标题,等,具体参考UI框架文档,DialogReactive Properties
|
||||
</n-alert>
|
||||
</n-card>
|
||||
|
||||
<basicModal @register="modalRegister" ref="modalRef" class="basicModal" @on-ok="okModal">
|
||||
<template #default>
|
||||
<BasicForm @register="register" @reset="handleReset" class="basicForm">
|
||||
<template #statusSlot="{ model, field }">
|
||||
<n-input v-model:value="model[field]" />
|
||||
</template>
|
||||
</BasicForm>
|
||||
</template>
|
||||
</basicModal>
|
||||
|
||||
<basicModal
|
||||
@register="lightModalRegister"
|
||||
class="basicModalLight"
|
||||
ref="modalRef"
|
||||
@on-ok="lightOkModal"
|
||||
>
|
||||
<template #default>
|
||||
<p class="text-gray-500" style="padding-left: 35px">一些对话框内容</p>
|
||||
</template>
|
||||
</basicModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, reactive, toRefs } from 'vue';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { basicModal, useModal } from '@/components/Modal';
|
||||
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
|
||||
|
||||
const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
component: 'NInput',
|
||||
label: '姓名',
|
||||
labelMessage: '这是一个提示',
|
||||
giProps: {
|
||||
span: 1,
|
||||
},
|
||||
componentProps: {
|
||||
placeholder: '请输入姓名',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
rules: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
|
||||
},
|
||||
{
|
||||
field: 'mobile',
|
||||
component: 'NInputNumber',
|
||||
label: '手机',
|
||||
componentProps: {
|
||||
placeholder: '请输入手机号码',
|
||||
showButton: false,
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'type',
|
||||
component: 'NSelect',
|
||||
label: '类型',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
componentProps: {
|
||||
placeholder: '请选择类型',
|
||||
options: [
|
||||
{
|
||||
label: '舒适性',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '经济性',
|
||||
value: 2,
|
||||
},
|
||||
],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeDate',
|
||||
component: 'NDatePicker',
|
||||
label: '预约时间',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
defaultValue: 1183135260000,
|
||||
componentProps: {
|
||||
type: 'date',
|
||||
clearable: true,
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeTime',
|
||||
component: 'NTimePicker',
|
||||
label: '停留时间',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
componentProps: {
|
||||
clearable: true,
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeProject',
|
||||
component: 'NCheckbox',
|
||||
label: '预约项目',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
componentProps: {
|
||||
placeholder: '请选择预约项目',
|
||||
options: [
|
||||
{
|
||||
label: '种牙',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '补牙',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '根管',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
onUpdateChecked: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'makeSource',
|
||||
component: 'NRadioGroup',
|
||||
label: '来源',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '网上',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '门店',
|
||||
value: 2,
|
||||
},
|
||||
],
|
||||
onUpdateChecked: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
label: '状态',
|
||||
giProps: {
|
||||
//span: 24,
|
||||
},
|
||||
//插槽
|
||||
slot: 'statusSlot',
|
||||
},
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
components: { basicModal, BasicForm },
|
||||
setup() {
|
||||
const modalRef: any = ref(null);
|
||||
const message = useMessage();
|
||||
|
||||
const [modalRegister, { openModal, closeModal, setSubLoading }] = useModal({
|
||||
title: '新增预约',
|
||||
});
|
||||
|
||||
const [
|
||||
lightModalRegister,
|
||||
{
|
||||
openModal: lightOpenModal,
|
||||
closeModal: lightCloseModal,
|
||||
setSubLoading: lightSetSubLoading,
|
||||
},
|
||||
] = useModal({
|
||||
title: '确认对话框',
|
||||
showIcon: true,
|
||||
type: 'warning',
|
||||
closable: false,
|
||||
maskClosable: true,
|
||||
});
|
||||
|
||||
const [register, { submit }] = useForm({
|
||||
gridProps: { cols: 1 },
|
||||
collapsedRows: 3,
|
||||
labelWidth: 120,
|
||||
layout: 'horizontal',
|
||||
submitButtonText: '提交预约',
|
||||
showActionButtonGroup: false,
|
||||
schemas,
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
formValue: {
|
||||
name: '小马哥',
|
||||
},
|
||||
});
|
||||
|
||||
async function okModal() {
|
||||
const formRes = await submit();
|
||||
if (formRes) {
|
||||
closeModal();
|
||||
console.log('formRes', formRes);
|
||||
message.success('提交成功');
|
||||
} else {
|
||||
message.error('验证失败,请填写完整信息');
|
||||
setSubLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
function lightOkModal() {
|
||||
lightCloseModal();
|
||||
lightSetSubLoading(false);
|
||||
}
|
||||
|
||||
function showLightModal() {
|
||||
lightOpenModal();
|
||||
}
|
||||
|
||||
function showModal() {
|
||||
openModal();
|
||||
}
|
||||
|
||||
function handleReset(values: Recordable) {
|
||||
console.log(values);
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
modalRef,
|
||||
register,
|
||||
modalRegister,
|
||||
lightModalRegister,
|
||||
handleReset,
|
||||
showModal,
|
||||
okModal,
|
||||
lightOkModal,
|
||||
showLightModal,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.basicForm {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.n-dialog.basicModal {
|
||||
width: 640px;
|
||||
}
|
||||
|
||||
.n-dialog.basicModalLight {
|
||||
width: 416px;
|
||||
padding-top: 26px;
|
||||
}
|
||||
</style>
|
||||
15
web/src/views/addons/hgexample/comp/moreComponents/index.vue
Normal file
15
web/src/views/addons/hgexample/comp/moreComponents/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<Iframe ref="iframeRef" style="zoom: 0.8" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import Iframe from '../../../../iframe/index.vue';
|
||||
|
||||
const iframeRef = ref();
|
||||
|
||||
onMounted(() => {
|
||||
iframeRef.value?.open('https://www.naiveui.com/zh-CN/os-theme/components/button');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
322
web/src/views/addons/hgexample/comp/notice/index.vue
Normal file
322
web/src/views/addons/hgexample/comp/notice/index.vue
Normal file
@@ -0,0 +1,322 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-grid :cols="2" :x-gap="10" :y-gap="10">
|
||||
<n-gi>
|
||||
<n-card
|
||||
title="警告信息alert"
|
||||
:content-style="{ padding: '10px' }"
|
||||
:header-style="{ padding: '10px' }"
|
||||
>
|
||||
<n-space vertical :size="12">
|
||||
<n-alert title="Info 类型" type="info"> 万事开头难,只能一直努力!!! </n-alert>
|
||||
<n-alert title="Success 类型" type="success">
|
||||
成功就是眼前,过了黑夜就是白天,加油~~
|
||||
</n-alert>
|
||||
<n-alert title="Warning 类型" type="warning">
|
||||
想想昨天,看看今天,望望明天;一切都会好起来
|
||||
</n-alert>
|
||||
<n-alert title="Error 类型" type="error"> 有人欺负人,请不犹豫,请还回去 </n-alert>
|
||||
<n-alert title="可以关掉" type="info" closable> Gee it's good to be back home </n-alert>
|
||||
<n-alert title="没有边框" type="info" :bordered="false">
|
||||
Gee it's good to be back home
|
||||
</n-alert>
|
||||
<n-alert title="自定义图标">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<BalloonOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
Well the Ukraine girls really knock me out<br />
|
||||
They leave the West behind<br />
|
||||
And Moscow girls make me sing and shout<br />
|
||||
That Georgia's always on my mind<br />
|
||||
Aw come on!
|
||||
</n-alert>
|
||||
|
||||
<n-alert :show-icon="false" title="没有图标">
|
||||
Yeah I'm back in the U.S.S.R.<br />
|
||||
You don't know how lucky you are boys
|
||||
</n-alert>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-card
|
||||
title="对话框Dialog"
|
||||
:content-style="{ padding: '10px' }"
|
||||
:header-style="{ padding: '10px' }"
|
||||
>
|
||||
<div class="padding">
|
||||
<n-space>
|
||||
<n-button size="small" type="primary" @click="openConfirm('warning')">警告</n-button>
|
||||
<n-button size="small" type="warning" @click="openConfirm('success')">成功</n-button>
|
||||
<n-button size="small" type="info" @click="openConfirm('error')">错误</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</n-card>
|
||||
<n-card
|
||||
class="mt-2"
|
||||
title="信息Message"
|
||||
:content-style="{ padding: '10px' }"
|
||||
:header-style="{ padding: '10px' }"
|
||||
>
|
||||
<n-space>
|
||||
<n-button type="info" @click="openMessage('info')"> 信息 </n-button>
|
||||
<n-button type="error" @click="openMessage('error')"> 错误 </n-button>
|
||||
<n-button type="warning" @click="openMessage('warning')"> 警告 </n-button>
|
||||
<n-button type="success" @click="openMessage('success')"> 成功 </n-button>
|
||||
<n-button type="primary" @click="openMessage('loading')"> 加载中 </n-button>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card
|
||||
class="mt-2"
|
||||
title="通知Notification"
|
||||
:content-style="{ padding: '10px' }"
|
||||
:header-style="{ padding: '10px' }"
|
||||
>
|
||||
<n-space>
|
||||
<n-button type="info" @click="openNotification('info')"> 信息 </n-button>
|
||||
<n-button type="error" @click="openNotification('error')"> 错误 </n-button>
|
||||
<n-button type="warning" @click="openNotification('warning')"> 警告 </n-button>
|
||||
<n-button type="success" @click="openNotification('success')"> 成功 </n-button>
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
<n-card
|
||||
class="mt-2"
|
||||
title="弹出确认Popconfirm"
|
||||
:content-style="{ padding: '10px' }"
|
||||
:header-style="{ padding: '10px' }"
|
||||
>
|
||||
<n-space>
|
||||
<n-popconfirm
|
||||
@positive-click="handlePositiveClick"
|
||||
@negative-click="handleNegativeClick"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-button>引用</n-button>
|
||||
</template>
|
||||
一切都将一去杳然,任何人都无法将其捕获。
|
||||
</n-popconfirm>
|
||||
<n-popconfirm :negative-text="null" @positive-click="handlePositiveClick">
|
||||
<template #trigger>
|
||||
<n-button>只有确定</n-button>
|
||||
</template>
|
||||
一切都将一去杳然,任何人都无法将其捕获。
|
||||
</n-popconfirm>
|
||||
<n-popconfirm :positive-text="null" @negative-click="handleNegativeClick">
|
||||
<template #trigger>
|
||||
<n-button>只有取消</n-button>
|
||||
</template>
|
||||
一切都将一去杳然,任何人都无法将其捕获。
|
||||
</n-popconfirm>
|
||||
<n-popconfirm :positive-text="null" :negative-text="null">
|
||||
<template #trigger>
|
||||
<n-button>什么也没有</n-button>
|
||||
</template>
|
||||
一切都将一去杳然,任何人都无法将其捕获。
|
||||
</n-popconfirm>
|
||||
<n-popconfirm>
|
||||
<template #trigger>
|
||||
<n-button>自定义 action</n-button>
|
||||
</template>
|
||||
<template #action> 自定义 action </template>
|
||||
一切都将一去杳然,任何人都无法将其捕获。
|
||||
</n-popconfirm>
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
<n-card
|
||||
class="mt-2"
|
||||
title="弹出信息Popover"
|
||||
:content-style="{ padding: '10px' }"
|
||||
:header-style="{ padding: '10px' }"
|
||||
>
|
||||
<n-space>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button>悬浮</n-button>
|
||||
</template>
|
||||
<span>I wish they all could be California girls</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="hover" :keep-alive-on-hover="false">
|
||||
<template #trigger>
|
||||
<n-button>悬浮(忽略主体)</n-button>
|
||||
</template>
|
||||
<span>I wish they all could be California girls</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="click">
|
||||
<template #trigger>
|
||||
<n-button>点击</n-button>
|
||||
</template>
|
||||
<span>I wish they all could be California girls</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="focus">
|
||||
<template #trigger>
|
||||
<n-button>聚焦</n-button>
|
||||
</template>
|
||||
<span>I wish they all could be California girls</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="manual" :show="showPopover">
|
||||
<template #trigger>
|
||||
<n-button @click="showPopover = !showPopover"> 手动 </n-button>
|
||||
</template>
|
||||
<span>I wish they all could be California girls</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="hover" :delay="500" :duration="500">
|
||||
<template #trigger>
|
||||
<n-button>延迟 500ms, 持续 500ms</n-button>
|
||||
</template>
|
||||
<span>
|
||||
Lately did you ever feel the pain In the morning rain as it soaks it to the bone
|
||||
</span>
|
||||
</n-popover>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card
|
||||
class="mt-2"
|
||||
title="弹出提示Tooltip"
|
||||
:content-style="{ padding: '10px' }"
|
||||
:header-style="{ padding: '10px' }"
|
||||
>
|
||||
<n-space>
|
||||
<n-tooltip trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button> 鸭子 </n-button>
|
||||
</template>
|
||||
如果它长得像鸭子,走起来像鸭子,叫起来也像鸭子,那它一定是个鸭子。
|
||||
</n-tooltip>
|
||||
<n-tooltip placement="bottom" trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button> 悬浮 </n-button>
|
||||
</template>
|
||||
<span> I wish they all could be California girls </span>
|
||||
</n-tooltip>
|
||||
<n-tooltip placement="bottom" trigger="click">
|
||||
<template #trigger>
|
||||
<n-button> 点击 </n-button>
|
||||
</template>
|
||||
<span> I wish they all could be California girls </span>
|
||||
</n-tooltip>
|
||||
<n-tooltip :show="showPopover" placement="bottom">
|
||||
<template #trigger>
|
||||
<n-button @click="showPopover = !showPopover"> 手动 </n-button>
|
||||
</template>
|
||||
<span> I wish they all could be California girls </span>
|
||||
</n-tooltip>
|
||||
<n-tooltip :show-arrow="false" trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button>默认有箭头</n-button>
|
||||
</template>
|
||||
和 Popover 一样
|
||||
</n-tooltip>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { useDialog, useMessage, useNotification } from 'naive-ui';
|
||||
import { BalloonOutline } from '@vicons/ionicons5';
|
||||
|
||||
const dialog = useDialog();
|
||||
const message = useMessage();
|
||||
const notification = useNotification();
|
||||
const showPopover = ref(false);
|
||||
|
||||
function openConfirm(type: string) {
|
||||
switch (type) {
|
||||
case 'warning':
|
||||
dialog.warning({
|
||||
title: '警告',
|
||||
content: '你确定要离开我?',
|
||||
positiveText: '确定',
|
||||
negativeText: '不确定',
|
||||
onPositiveClick: () => {
|
||||
message.success('确定');
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
message.error('不确定');
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'success':
|
||||
dialog.success({
|
||||
title: '成功',
|
||||
content: '小哥哥你太棒了~~',
|
||||
positiveText: '哇哦~',
|
||||
});
|
||||
break;
|
||||
case 'error':
|
||||
dialog.error({
|
||||
title: '错误',
|
||||
content: '知道错了吗,下次改了',
|
||||
positiveText: '快哭了',
|
||||
onPositiveClick: () => {
|
||||
message.success('我知道了');
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function openMessage(type: string) {
|
||||
switch (type) {
|
||||
case 'info':
|
||||
message.info('在心碎中认清遗憾 生命漫长也短暂跳动心脏长出藤蔓');
|
||||
break;
|
||||
case 'error':
|
||||
message.error('愿为险而战 跌入灰暗坠入深渊');
|
||||
break;
|
||||
case 'warning':
|
||||
message.warning('沾满泥土的脸 没有神的光环');
|
||||
break;
|
||||
case 'success':
|
||||
message.success('握紧手中的平凡 此心自称无憾生命的火已点燃');
|
||||
break;
|
||||
case 'loading':
|
||||
message.loading('有一天也许会走远 也许还能再相见');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function openNotification(type: string) {
|
||||
switch (type) {
|
||||
case 'info':
|
||||
notification.info({
|
||||
content: '在心碎中认清遗憾 生命漫长也短暂跳动心脏长出藤蔓',
|
||||
meta: '只要平凡',
|
||||
});
|
||||
break;
|
||||
case 'error':
|
||||
notification.error({
|
||||
content: '愿为险而战 跌入灰暗坠入深渊',
|
||||
meta: '只要平凡',
|
||||
});
|
||||
break;
|
||||
case 'warning':
|
||||
notification.warning({
|
||||
content: '沾满泥土的脸 没有神的光环',
|
||||
meta: '只要平凡',
|
||||
});
|
||||
break;
|
||||
case 'success':
|
||||
notification.success({
|
||||
content: '握紧手中的平凡 此心自称无憾生命的火已点燃',
|
||||
meta: '只要平凡',
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handlePositiveClick() {
|
||||
message.info('是的');
|
||||
}
|
||||
|
||||
function handleNegativeClick() {
|
||||
message.info('并不');
|
||||
}
|
||||
</script>
|
||||
109
web/src/views/addons/hgexample/comp/print/index.vue
Normal file
109
web/src/views/addons/hgexample/comp/print/index.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<n-card title="打印图片" :header-style="{ padding: '5px' }" :content-style="{ padding: '0px' }">
|
||||
<template #header-extra>
|
||||
<n-button type="primary" size="small" @click="printImage">打印</n-button>
|
||||
</template>
|
||||
<div class="image-wrapper">
|
||||
<img :src="imagePath" />
|
||||
</div>
|
||||
</n-card>
|
||||
<n-card
|
||||
title="打印HTML"
|
||||
:header-style="{ padding: '5px' }"
|
||||
:content-style="{ padding: '0px' }"
|
||||
class="mt-4"
|
||||
>
|
||||
<template #header-extra>
|
||||
<n-button type="primary" size="small" @click="printHtml">打印</n-button>
|
||||
</template>
|
||||
<div id="htmlWrapper" class="flex justify-center html-wrapper align-center flex-direction">
|
||||
<n-table :data="dataList">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>姓名</th>
|
||||
<th>年龄</th>
|
||||
<th>性别</th>
|
||||
<th>职业</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) of dataList" :key="index">
|
||||
<td>{{ item.name }}</td>
|
||||
<td>{{ item.age }}</td>
|
||||
<td>{{ item.gender }}</td>
|
||||
<td>{{ item.career }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</n-table>
|
||||
</div>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import printJS from 'print-js';
|
||||
import imagePath from '@/assets/images/logo.png';
|
||||
import { defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'Print',
|
||||
setup() {
|
||||
function printImage() {
|
||||
printJS({
|
||||
printable: imagePath,
|
||||
type: 'image',
|
||||
showModal: false,
|
||||
});
|
||||
}
|
||||
function printHtml() {
|
||||
printJS({
|
||||
printable: 'htmlWrapper',
|
||||
type: 'html',
|
||||
targetStyles: ['*'],
|
||||
});
|
||||
}
|
||||
return {
|
||||
printImage,
|
||||
printHtml,
|
||||
imagePath,
|
||||
dataList: [
|
||||
{
|
||||
name: '张三',
|
||||
age: 30,
|
||||
gender: '男',
|
||||
career: '工程师',
|
||||
},
|
||||
{
|
||||
name: '李四',
|
||||
age: 20,
|
||||
gender: '男',
|
||||
career: '服务员',
|
||||
},
|
||||
{
|
||||
name: '王五',
|
||||
age: 40,
|
||||
gender: '女',
|
||||
career: '售货员',
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.image-wrapper {
|
||||
width: 30%;
|
||||
margin: 0 auto;
|
||||
& > img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.html-wrapper {
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
& > h1 {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
70
web/src/views/addons/hgexample/comp/result/fail.vue
Normal file
70
web/src/views/addons/hgexample/comp/result/fail.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<n-card :bordered="false" class="proCard">
|
||||
<div class="result-box">
|
||||
<n-result status="error" title="操作失败" description="请核对并修改以下信息后,再重新提交。">
|
||||
<div class="result-box-extra">
|
||||
<p>您提交的内容有如下错误:</p>
|
||||
<p class="mt-3">
|
||||
<n-space align="center">
|
||||
<n-icon size="20" color="#f0a020">
|
||||
<InfoCircleOutlined />
|
||||
</n-icon>
|
||||
<span>认证照片不够清晰</span>
|
||||
<n-button type="info" text>立即修改</n-button>
|
||||
</n-space>
|
||||
</p>
|
||||
<p class="mt-3">
|
||||
<n-space>
|
||||
<n-icon size="20" color="#f0a020">
|
||||
<InfoCircleOutlined />
|
||||
</n-icon>
|
||||
<span>备注包含敏感字符,并且不能包含政治相关</span>
|
||||
<n-button type="info" text>立即修改</n-button>
|
||||
</n-space>
|
||||
</p>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex justify-center mb-4">
|
||||
<n-space align="center">
|
||||
<n-button type="info" @click="goHome">回到首页</n-button>
|
||||
<n-button>查看详情</n-button>
|
||||
<n-button>打印</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
</n-result>
|
||||
</div>
|
||||
</n-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { useThemeVars } from 'naive-ui';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { InfoCircleOutlined } from '@vicons/antd';
|
||||
|
||||
const router = useRouter();
|
||||
const themeVars = useThemeVars();
|
||||
|
||||
const getTableHeaderColor = computed(() => {
|
||||
return themeVars.value.tableHeaderColor;
|
||||
});
|
||||
|
||||
function goHome() {
|
||||
router.push('/');
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.result-box {
|
||||
width: 72%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding-top: 5px;
|
||||
|
||||
&-extra {
|
||||
padding: 24px 40px;
|
||||
text-align: left;
|
||||
background: v-bind(getTableHeaderColor);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
74
web/src/views/addons/hgexample/comp/result/info.vue
Normal file
74
web/src/views/addons/hgexample/comp/result/info.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<n-card :bordered="false" class="proCard">
|
||||
<div class="result-box">
|
||||
<n-result
|
||||
status="info"
|
||||
title="提示"
|
||||
description="本次提交,将在24小时候内自动转入对方账户,如操作失误,请及时撤回"
|
||||
>
|
||||
<div class="result-box-extra">
|
||||
<p>您提交的内容如下:</p>
|
||||
<p class="mt-3">
|
||||
<n-space align="center">
|
||||
<n-icon size="20" color="#18a058">
|
||||
<CheckCircleOutlined />
|
||||
</n-icon>
|
||||
<span>转入支付宝账户(189****5426):¥1980元</span>
|
||||
<n-button type="info" text>立即撤回</n-button>
|
||||
</n-space>
|
||||
</p>
|
||||
<p class="mt-3">
|
||||
<n-space>
|
||||
<n-icon size="20" color="#18a058">
|
||||
<CheckCircleOutlined />
|
||||
</n-icon>
|
||||
<span>转入支付宝账户(187****5426):¥2980元</span>
|
||||
<n-button type="info" text>立即撤回</n-button>
|
||||
</n-space>
|
||||
</p>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex justify-center mb-4">
|
||||
<n-space align="center">
|
||||
<n-button type="info" @click="goHome">回到首页</n-button>
|
||||
<n-button>查看详情</n-button>
|
||||
<n-button>全部撤回</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
</n-result>
|
||||
</div>
|
||||
</n-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { useThemeVars } from 'naive-ui';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { CheckCircleOutlined } from '@vicons/antd';
|
||||
|
||||
const router = useRouter();
|
||||
const themeVars = useThemeVars();
|
||||
|
||||
const getTableHeaderColor = computed(() => {
|
||||
return themeVars.value.tableHeaderColor;
|
||||
});
|
||||
|
||||
function goHome() {
|
||||
router.push('/');
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.result-box {
|
||||
width: 72%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding-top: 5px;
|
||||
|
||||
&-extra {
|
||||
padding: 24px 40px;
|
||||
text-align: left;
|
||||
background: v-bind(getTableHeaderColor);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
55
web/src/views/addons/hgexample/comp/result/success.vue
Normal file
55
web/src/views/addons/hgexample/comp/result/success.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<n-card :bordered="false" class="proCard">
|
||||
<div class="result-box">
|
||||
<n-result
|
||||
status="success"
|
||||
title="操作成功"
|
||||
description="提交结果页用于反馈一系列操作任务的处理结果,如果仅是简单操作,灰色区域可以显示一些补充的信息。"
|
||||
>
|
||||
<div class="result-box-extra">
|
||||
<p>已提交申请,等待财务部门审核。</p>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex justify-center mb-4">
|
||||
<n-space align="center">
|
||||
<n-button type="info" @click="goHome">回到首页</n-button>
|
||||
<n-button>查看详情</n-button>
|
||||
<n-button>打印</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
</n-result>
|
||||
</div>
|
||||
</n-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useThemeVars } from 'naive-ui';
|
||||
|
||||
const router = useRouter();
|
||||
const themeVars = useThemeVars();
|
||||
|
||||
const getTableHeaderColor = computed(() => {
|
||||
return themeVars.value.tableHeaderColor;
|
||||
});
|
||||
|
||||
function goHome() {
|
||||
router.push('/');
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.result-box {
|
||||
width: 72%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding-top: 5px;
|
||||
|
||||
&-extra {
|
||||
padding: 24px 40px;
|
||||
text-align: left;
|
||||
background: v-bind(getTableHeaderColor);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
26
web/src/views/addons/hgexample/comp/tagsView/index.vue
Normal file
26
web/src/views/addons/hgexample/comp/tagsView/index.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="tagsView"> 标签页操作项 </n-card>
|
||||
</div>
|
||||
<n-card>
|
||||
<n-space>
|
||||
<n-button type="info" @click="handleSignal('1')"> 刷新页面路由 </n-button>
|
||||
<n-button type="error" @click="handleSignal('2')"> 关闭当前页面 </n-button>
|
||||
<n-button type="warning" @click="handleSignal('3')"> 关闭其他页面 </n-button>
|
||||
<n-button type="success" @click="handleSignal('4')"> 关闭全部页面 </n-button>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useTabsViewStore } from '@/store/modules/tabsView';
|
||||
|
||||
const tabsViewStore = useTabsViewStore();
|
||||
|
||||
function handleSignal(signal: string) {
|
||||
tabsViewStore.closeSignal(signal);
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
70
web/src/views/addons/hgexample/comp/text/gradient/index.vue
Normal file
70
web/src/views/addons/hgexample/comp/text/gradient/index.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-space vertical>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 渐变文字 </template>
|
||||
<template #header-extra>
|
||||
<n-gradient-text type="success"> 渐变文字成了 </n-gradient-text>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-gradient-text style="white-space: normal" type="success">
|
||||
<p
|
||||
>苏轼,(1037年1月8日-1101年8月24日)字子瞻、和仲,号铁冠道人、东坡居士,世称苏东坡、苏仙,汉族,眉州眉山(四川省眉山市)人,祖籍河北栾城,北宋著名文学家、书法家、画家,历史治水名人。苏轼是北宋中期文坛领袖,在诗、词、散文、书、画等方面取得很高成就。文纵横恣肆;诗题材广阔,清新豪健,善用夸张比喻,独具风格,与黄庭坚并称“苏黄”;词开豪放一派,与辛弃疾同是豪放派代表,并称“苏辛”;散文著述宏富,豪放自如,与欧阳修并称“欧苏”,为“唐宋八大家”之一。苏轼善书,“宋四家”之一;擅长文人画,尤擅墨竹、怪石、枯木等。与韩愈、柳宗元和欧阳修合称“千古文章四大家”。作品有《东坡七集》《东坡易传》《东坡乐府》《潇湘竹石图卷》《古木怪石图卷》等</p
|
||||
>
|
||||
</n-gradient-text>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 渐变文字 </template>
|
||||
<template #header-extra>
|
||||
<n-gradient-text type="warning"> 渐变文字成了 </n-gradient-text>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-gradient-text style="white-space: normal" type="warning">
|
||||
<p
|
||||
>白居易(772年-846年),字乐天,号香山居士,又号醉吟先生,祖籍太原,到其曾祖父时迁居下邽,生于河南新郑。是唐代伟大的现实主义诗人,唐代三大诗人之一。白居易与元稹共同倡导新乐府运动,世称“元白”,与刘禹锡并称“刘白”。白居易的诗歌题材广泛,形式多样,语言平易通俗,有“诗魔”和“诗王”之称。官至翰林学士、左赞善大夫。公元846年,白居易在洛阳逝世,葬于香山。有《白氏长庆集》传世,代表诗作有《长恨歌》《卖炭翁》《琵琶行》等。</p
|
||||
>
|
||||
</n-gradient-text>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 自定义颜色 </template>
|
||||
<template #header-extra>
|
||||
<n-gradient-text gradient="linear-gradient(90deg, red 0%, green 50%, blue 100%)">
|
||||
渐变文字成了
|
||||
</n-gradient-text>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-gradient-text
|
||||
gradient="linear-gradient(90deg, red 0%, green 50%, blue 100%)"
|
||||
style="white-space: normal"
|
||||
>
|
||||
<p
|
||||
>杜甫(712-770),字子美,自号少陵野老,世称“杜工部”、“杜少陵”等,汉族,河南府巩县(今河南省巩义市)人,唐代伟大的现实主义诗人,杜甫被世人尊为“诗圣”,其诗被称为“诗史”。杜甫与李白合称“李杜”,为了跟另外两位诗人李商隐与杜牧即“小李杜”区别开来,杜甫与李白又合称“大李杜”。他忧国忧民,人格高尚,他的约1400余首诗被保留了下来,诗艺精湛,在中国古典诗歌中备受推崇,影响深远。759-766年间曾居成都,后世有杜甫草堂纪念</p
|
||||
>
|
||||
</n-gradient-text>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup></script>
|
||||
<style lang="less" scoped>
|
||||
p {
|
||||
font-size: 14px;
|
||||
line-height: 2;
|
||||
text-indent: 28px;
|
||||
}
|
||||
</style>
|
||||
94
web/src/views/addons/hgexample/comp/text/high/index.vue
Normal file
94
web/src/views/addons/hgexample/comp/text/high/index.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-card title="高亮" style="margin-bottom: 10px">
|
||||
<n-text>
|
||||
<p style="line-height: 2" v-html="compData1.text"></p>
|
||||
</n-text>
|
||||
</n-card>
|
||||
<n-card title="自定义颜色" style="margin-bottom: 10px">
|
||||
<n-text>
|
||||
<p style="line-height: 2" v-html="compData2.text"></p>
|
||||
</n-text>
|
||||
</n-card>
|
||||
<n-card title="自定义样式">
|
||||
<n-text>
|
||||
<p style="line-height: 2" v-html="compData3.text"></p>
|
||||
</n-text>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import highHtml from '@/utils/highHtml';
|
||||
import { reactive, onMounted } from 'vue';
|
||||
|
||||
const text =
|
||||
'先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。\n' +
|
||||
'\n' +
|
||||
' 宫中府中,俱为一体;陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。\n' +
|
||||
'\n' +
|
||||
' 侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。\n' +
|
||||
'\n' +
|
||||
' 将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。\n' +
|
||||
'\n' +
|
||||
' 亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。\n' +
|
||||
'\n' +
|
||||
' 臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。\n' +
|
||||
'\n' +
|
||||
' 先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐托付不效,以伤先帝之明;故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。\n' +
|
||||
'\n' +
|
||||
' 愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏。臣不胜受恩感激。今当远离,临表涕零,不知所言';
|
||||
|
||||
const compData1 = reactive({
|
||||
text: '',
|
||||
keys: ['先帝', '先汉', '苟'],
|
||||
});
|
||||
const compData2 = reactive({
|
||||
text: '',
|
||||
keys: [
|
||||
{
|
||||
keyword: '先帝',
|
||||
bgColor: 'red',
|
||||
color: '#fff',
|
||||
renderHighlightKeyword: (str) => {
|
||||
return `<span class="high" style="padding:2px 5px;margin:0 5px;border-radius:3px;background-color: #3a5ccc;color: #ffffff">${str}</span>`;
|
||||
},
|
||||
},
|
||||
{
|
||||
keyword: '中',
|
||||
bgColor: '#b4d5ff',
|
||||
color: '#fff',
|
||||
renderHighlightKeyword: (str) => {
|
||||
return `<span class="high" style="padding:2px 5px;margin:0 5px;border-radius:3px;background-color: #e96656;color: #ffffff">${str}</span>`;
|
||||
},
|
||||
},
|
||||
{ keyword: '苟', bgColor: '#b4d5ff', color: '#fff' },
|
||||
],
|
||||
});
|
||||
const compData3 = reactive({
|
||||
text: '',
|
||||
keys: [
|
||||
{
|
||||
keyword: '之',
|
||||
bgColor: 'red',
|
||||
color: '#fff',
|
||||
style: { padding: '2px 5px', margin: '0 5px', 'border-radius': '3px' },
|
||||
},
|
||||
{ keyword: '先帝', bgColor: '#b4d5ff', color: '#fff' },
|
||||
{ keyword: '苟', bgColor: '#b4d5ff', color: '#fff' },
|
||||
],
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
compData1.text = highHtml(text, compData1.keys).highText;
|
||||
compData2.text = highHtml(text, compData2.keys).highText;
|
||||
compData3.text = highHtml(text, compData3.keys).highText;
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
.high {
|
||||
&:hover {
|
||||
background-color: seagreen !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
50
web/src/views/addons/hgexample/comp/text/mint/index.vue
Normal file
50
web/src/views/addons/hgexample/comp/text/mint/index.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 敏感词汇验证 </template>
|
||||
<n-space vertical>
|
||||
<n-space>
|
||||
<n-tag
|
||||
:type="idx % 2 ? 'success' : 'warning'"
|
||||
:key="idx"
|
||||
v-for="(item, idx) in compData.keys"
|
||||
>{{ item }}</n-tag
|
||||
>
|
||||
</n-space>
|
||||
<n-input
|
||||
placeholder="输入需要验证的词汇文本"
|
||||
type="textarea"
|
||||
size="small"
|
||||
v-model:value="compData.text"
|
||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
||||
@update:value="compData.handleUpdateText"
|
||||
/>
|
||||
<n-space>
|
||||
<n-tag
|
||||
:type="idx % 2 ? 'error' : 'info'"
|
||||
:key="idx"
|
||||
v-for="(item, idx) in compData.words"
|
||||
>{{ item }}</n-tag
|
||||
>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import Mint from 'mint-filter';
|
||||
|
||||
const compData = reactive({
|
||||
keys: ['敏感词', '胡萝卜', '香蕉', '苹果'],
|
||||
text: '',
|
||||
words: [],
|
||||
});
|
||||
const mint = new Mint(compData.keys);
|
||||
compData.handleUpdateText = (value: string | [string, string]) => {
|
||||
const test = mint.filter(value);
|
||||
compData.words = test.words;
|
||||
};
|
||||
</script>
|
||||
102
web/src/views/addons/hgexample/comp/text/pinyin/index.vue
Normal file
102
web/src/views/addons/hgexample/comp/text/pinyin/index.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-space vertical>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 字符拼音 </template>
|
||||
<template #header-extra> 陋室铭,唐代:刘禹锡 </template>
|
||||
<div class="pinyin">
|
||||
<template v-for="item in compData.items1">
|
||||
<div class="pinyin-item" :key="idx" v-for="(todo, idx) in item">
|
||||
<span class="py">{{ todo.py }}</span>
|
||||
<span class="hz">{{ todo.hz }}</span> </div
|
||||
><br />
|
||||
</template>
|
||||
</div>
|
||||
</n-card>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 字符拼音 </template>
|
||||
<template #header-extra> 李贺小传,李商隐〔唐代〕 </template>
|
||||
<div class="pinyin">
|
||||
<template v-for="item in compData.items2">
|
||||
<div class="pinyin-item" :key="idx" v-for="(todo, idx) in item">
|
||||
<span class="py">{{ todo.py }}</span>
|
||||
<span class="hz">{{ todo.hz }}</span> </div
|
||||
><br />
|
||||
</template>
|
||||
</div>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { pinyin } from 'pinyin-pro';
|
||||
|
||||
interface WordInfo {
|
||||
hz: string;
|
||||
py: string;
|
||||
}
|
||||
|
||||
const text1 = [
|
||||
' 山不在高,有仙则名。水不在深,有龙则灵。斯是陋室,惟吾德馨。苔痕上阶绿,草色入帘青。谈笑有鸿儒,往来无白丁。可以调素琴,阅金经。无丝竹之乱耳,无案牍之劳形。南阳诸葛庐,西蜀子云亭。孔子云:何陋之有?',
|
||||
];
|
||||
const text2 = [
|
||||
' 京兆杜牧为李长吉集序,状长吉之奇甚尽,世传之。长吉姊嫁王氏者,语长吉之事尤备。',
|
||||
' 长吉细瘦,通眉,长指爪,能苦吟疾书。最先为昌黎韩愈所知。所与游者,王参元、杨敬之、权璩、崔植辈为密,每旦日出与诸公游,未尝得题然后为诗,如他人思量牵合,以及程限为意。恒从小奚奴,骑距驉,背一古破锦囊,遇有所得,即书投囊中。及暮归.太夫人使婢受囊出之,见所书多.辄曰:“是儿要当呕出心乃已尔。”上灯,与食。长吉从婢取书,研墨叠纸足成之,投他囊中。非大醉及吊丧日率如此,过亦不复省。王、杨辈时复来探取写去。长吉往往独骑往还京、洛,所至或时有著,随弃之,故沈子明家所余四卷而已。',
|
||||
' 长吉将死时,忽昼见一绯衣人,驾赤虬,持一板,书若太古篆或霹雳石文者,云当召长吉。长吉了不能读,欻下榻叩头,言:“阿㜷老且病,贺不愿去。”绯衣人笑曰:“帝成白玉楼,立召君为记。天上差乐,不苦也。”长吉独泣,边人尽见之。少之,长吉气绝。常所居窗中,勃勃有烟气,闻行车嘒管之声。太夫人急止人哭,待之如炊五斗黍许时,长吉竟死。王氏姊非能造作谓长吉者,实所见如此。',
|
||||
' 呜呼,天苍苍而高也,上果有帝耶?帝果有苑囿、宫室、观阁之玩耶?苟信然,则天之高邈,帝之尊严,亦宜有人物文采愈此世者,何独眷眷于长吉而使其不寿耶?噫,又岂世所谓才而奇者,不独地上少,即天上亦不多耶?长吉生二十七年,位不过奉礼太常,时人亦多排摈毁斥之,又岂才而奇者,帝独重之,而人反不重耶?又岂人见会胜帝耶?',
|
||||
];
|
||||
|
||||
const createHzPy = (text: string[]): WordInfo[][] => {
|
||||
const items: WordInfo[][] = [];
|
||||
text.forEach((item) => {
|
||||
const todo: WordInfo[] = [];
|
||||
for (let i = 0; i < item.length; i++) {
|
||||
const tg = item.charAt(i);
|
||||
todo.push({ hz: tg, py: pinyin(tg)[0] });
|
||||
}
|
||||
items.push(todo);
|
||||
});
|
||||
return items;
|
||||
};
|
||||
|
||||
const compData = reactive({
|
||||
items1: createHzPy(text1),
|
||||
items2: createHzPy(text2),
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.pinyin {
|
||||
&-item {
|
||||
line-height: 100%;
|
||||
width: 42px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
.py {
|
||||
clear: both;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
float: left;
|
||||
width: 42px;
|
||||
}
|
||||
.hz {
|
||||
clear: both;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
float: left;
|
||||
font-size: 16px;
|
||||
height: 36px;
|
||||
width: 42px;
|
||||
line-height: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
97
web/src/views/addons/hgexample/comp/timeline/index.vue
Normal file
97
web/src/views/addons/hgexample/comp/timeline/index.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 时间线 </template>
|
||||
<n-space>
|
||||
<n-card title="竖向">
|
||||
<n-timeline>
|
||||
<n-timeline-item content="啊" />
|
||||
<n-timeline-item type="success" title="成功" content="哪里成功" time="2018-04-03 20:46" />
|
||||
<n-timeline-item type="error" content="哪里错误" time="2018-04-03 20:46" />
|
||||
<n-timeline-item type="warning" title="警告" content="哪里警告" time="2018-04-03 20:46" />
|
||||
<n-timeline-item
|
||||
type="info"
|
||||
title="信息"
|
||||
content="是的"
|
||||
time="2018-04-03 20:46"
|
||||
line-type="dashed"
|
||||
/>
|
||||
<n-timeline-item content="啊" />
|
||||
</n-timeline>
|
||||
</n-card>
|
||||
<n-card title="横向">
|
||||
<div style="overflow: auto">
|
||||
<n-timeline horizontal>
|
||||
<n-timeline-item content="啊" />
|
||||
<n-timeline-item
|
||||
type="success"
|
||||
title="成功"
|
||||
content="哪里成功"
|
||||
time="2018-04-03 20:46"
|
||||
/>
|
||||
<n-timeline-item type="error" content="哪里失败" time="2018-04-03 20:46" />
|
||||
<n-timeline-item
|
||||
type="warning"
|
||||
title="警告"
|
||||
content="哪里警告"
|
||||
time="2018-04-03 20:46"
|
||||
/>
|
||||
<n-timeline-item type="info" title="信息" content="是的" time="2018-04-03 20:46" />
|
||||
</n-timeline>
|
||||
</div>
|
||||
</n-card>
|
||||
<n-card title="自定义">
|
||||
<n-timeline :icon-size="20">
|
||||
<n-timeline-item color="grey" content="啊">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<cash-icon />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-timeline-item>
|
||||
<n-timeline-item type="success" title="成功" content="哪里成功" time="2018-04-03 20:46">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<cash-icon />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-timeline-item>
|
||||
<n-timeline-item type="error" content="哪里错误" time="2018-04-03 20:46">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<cash-icon />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-timeline-item>
|
||||
<n-timeline-item type="warning" title="警告" content="哪里警告" time="2018-04-03 20:46">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<cash-icon />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-timeline-item>
|
||||
<n-timeline-item type="info" title="信息" content="是的" time="2018-04-03 20:46">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<cash-icon />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-timeline-item>
|
||||
</n-timeline>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { CashOutline as CashIcon } from '@vicons/ionicons5';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
CashIcon,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
15
web/src/views/addons/hgexample/comp/vis/echarts.vue
Normal file
15
web/src/views/addons/hgexample/comp/vis/echarts.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<Iframe ref="iframeRef" style="zoom: 0.8" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import Iframe from '../../../../iframe/index.vue';
|
||||
|
||||
const iframeRef = ref();
|
||||
|
||||
onMounted(() => {
|
||||
iframeRef.value?.open('https://www.makeapie.cn/echarts');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
15
web/src/views/addons/hgexample/comp/vis/madeapie.vue
Normal file
15
web/src/views/addons/hgexample/comp/vis/madeapie.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<Iframe ref="iframeRef" style="zoom: 0.9" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import Iframe from '../../../../iframe/index.vue';
|
||||
|
||||
const iframeRef = ref();
|
||||
|
||||
onMounted(() => {
|
||||
iframeRef.value?.open('https://madeapie.com/');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
15
web/src/views/addons/hgexample/comp/vis/ppchart.vue
Normal file
15
web/src/views/addons/hgexample/comp/vis/ppchart.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<Iframe ref="iframeRef" style="zoom: 0.9" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import Iframe from '../../../../iframe/index.vue';
|
||||
|
||||
const iframeRef = ref();
|
||||
|
||||
onMounted(() => {
|
||||
iframeRef.value?.open('https://ppchart.com/#/');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
106
web/src/views/addons/hgexample/comp/waterfall/index.vue
Normal file
106
web/src/views/addons/hgexample/comp/waterfall/index.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 瀑布流组件 </template>
|
||||
<template #header-extra>
|
||||
<n-tag type="success" @click="handleClick">vue-waterfall-plugin-next</n-tag>
|
||||
</template>
|
||||
<Waterfall
|
||||
:row-key="options.rowKey"
|
||||
:gutter="options.gutter"
|
||||
:has-around-gutter="options.hasAroundGutter"
|
||||
:width="options.width"
|
||||
:breakpoints="options.breakpoints"
|
||||
:img-selector="options.imgSelector"
|
||||
:background-color="options.backgroundColor"
|
||||
:animation-effect="options.animationEffect"
|
||||
:animation-duration="options.animationDuration"
|
||||
:animation-delay="options.animationDelay"
|
||||
:lazyload="options.lazyload"
|
||||
:list="compData.items"
|
||||
>
|
||||
<template #item="{ item }">
|
||||
<div class="waterfall-item" :style="item.style">
|
||||
<span>君问归期未有期,巴山夜雨涨秋池。何当共剪西窗烛,却话巴山夜雨时。</span>
|
||||
</div>
|
||||
</template>
|
||||
</Waterfall>
|
||||
</n-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { Waterfall } from 'vue-waterfall-plugin-next';
|
||||
import 'vue-waterfall-plugin-next/dist/style.css';
|
||||
import { rdmLightRgbColor } from '@/utils/hotgo';
|
||||
|
||||
const options = reactive({
|
||||
// 唯一key值
|
||||
rowKey: 'id',
|
||||
// 卡片之间的间隙
|
||||
gutter: 20,
|
||||
// 是否有周围的gutter
|
||||
hasAroundGutter: true,
|
||||
// 卡片在PC上的宽度
|
||||
width: 250,
|
||||
// 自定义行显示个数,主要用于对移动端的适配
|
||||
breakpoints: {
|
||||
1200: {
|
||||
// 当屏幕宽度小于等于1200
|
||||
rowPerView: 5,
|
||||
},
|
||||
800: {
|
||||
// 当屏幕宽度小于等于800
|
||||
rowPerView: 3,
|
||||
},
|
||||
500: {
|
||||
// 当屏幕宽度小于等于500
|
||||
rowPerView: 1,
|
||||
},
|
||||
},
|
||||
// 动画效果
|
||||
animationEffect: 'animate__fadeInUp',
|
||||
// 动画时间
|
||||
animationDuration: 1000,
|
||||
// 动画延迟
|
||||
animationDelay: 300,
|
||||
// 背景色
|
||||
backgroundColor: '',
|
||||
// imgSelector
|
||||
imgSelector: 'src.original',
|
||||
// 是否懒加载
|
||||
lazyload: true,
|
||||
});
|
||||
|
||||
const items: any = [];
|
||||
const genBetweenRight = (m, n) => Math.floor(Math.random() * (n - m) + 1) + m;
|
||||
for (let i = 0; i < 90; i++) {
|
||||
items.push({
|
||||
style: {
|
||||
height: genBetweenRight(100, 300) + 'px',
|
||||
'background-color': rdmLightRgbColor(),
|
||||
},
|
||||
});
|
||||
}
|
||||
const compData = reactive({
|
||||
items,
|
||||
});
|
||||
const handleClick = () => {
|
||||
window.open('https://vue-waterfall.netlify.app/');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.waterfall-item {
|
||||
border: 2px solid rgb(244, 244, 248);
|
||||
height: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
171
web/src/views/addons/hgexample/comp/watermark/index.vue
Normal file
171
web/src/views/addons/hgexample/comp/watermark/index.vue
Normal file
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<n-space vertical>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 文字水印 </template>
|
||||
<template #header-extra> 核心机密 </template>
|
||||
<n-watermark
|
||||
content="核心机密"
|
||||
cross
|
||||
selectable
|
||||
:font-size="16"
|
||||
:line-height="16"
|
||||
:width="192"
|
||||
:height="128"
|
||||
:x-offset="12"
|
||||
:y-offset="28"
|
||||
:rotate="-15"
|
||||
>
|
||||
<n-table :single-line="false">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>复盘</th>
|
||||
<th>赋能</th>
|
||||
<th>协同</th>
|
||||
<th>...</th>
|
||||
<th>串联</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>拉通</td>
|
||||
<td>打通</td>
|
||||
<td>树立</td>
|
||||
<td>...</td>
|
||||
<td>履约</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</n-table>
|
||||
</n-watermark>
|
||||
</n-card>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 图片水印 </template>
|
||||
<template #header-extra>
|
||||
<n-image height="30" width="30" :src="compData.img" />
|
||||
</template>
|
||||
<n-watermark
|
||||
:image="compData.img"
|
||||
cross
|
||||
:rotate="-15"
|
||||
:font-size="16"
|
||||
:line-height="16"
|
||||
:width="192"
|
||||
:height="128"
|
||||
:x-offset="12"
|
||||
:y-offset="30"
|
||||
:image-width="34"
|
||||
:image-opacity="0.24"
|
||||
>
|
||||
<n-table :single-line="false">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>复盘</th>
|
||||
<th>赋能</th>
|
||||
<th>协同</th>
|
||||
<th>...</th>
|
||||
<th>串联</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>拉通</td>
|
||||
<td>打通</td>
|
||||
<td>树立</td>
|
||||
<td>...</td>
|
||||
<td>履约</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</n-table>
|
||||
</n-watermark>
|
||||
</n-card>
|
||||
<n-card
|
||||
:segmented="{ content: true, footer: true }"
|
||||
header-style="padding:10px"
|
||||
footer-style="padding:10px"
|
||||
>
|
||||
<template #header> 自定义水印 </template>
|
||||
<template #header-extra>
|
||||
<n-input-group>
|
||||
<n-input v-model:value="compData.text" placeholder="输入自定义水印" />
|
||||
<n-button type="primary" ghost>添加</n-button>
|
||||
</n-input-group>
|
||||
</template>
|
||||
<n-watermark
|
||||
v-model:content="compData.text"
|
||||
cross
|
||||
selectable
|
||||
:font-size="16"
|
||||
:line-height="16"
|
||||
:width="192"
|
||||
:height="128"
|
||||
:x-offset="12"
|
||||
:y-offset="28"
|
||||
:rotate="-15"
|
||||
>
|
||||
<n-table :single-line="false">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>复盘</th>
|
||||
<th>赋能</th>
|
||||
<th>协同</th>
|
||||
<th>...</th>
|
||||
<th>串联</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>拉通</td>
|
||||
<td>打通</td>
|
||||
<td>树立</td>
|
||||
<td>...</td>
|
||||
<td>履约</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
<td>...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</n-table>
|
||||
</n-watermark>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive } from 'vue';
|
||||
import logo from '@/assets/images/logo.png';
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const compData = reactive({
|
||||
img: logo,
|
||||
text: '自定义水印',
|
||||
});
|
||||
return {
|
||||
compData,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -7,7 +7,7 @@
|
||||
</n-input-group>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="二维码" path="index">
|
||||
<n-form-item label="二维码" path="index" v-if="showQrcode">
|
||||
<div class="text-center">
|
||||
<qrcode-vue :value="url" :size="220" class="canvas" style="margin: 0 auto" />
|
||||
</div>
|
||||
@@ -24,10 +24,12 @@
|
||||
|
||||
interface Props {
|
||||
path: string;
|
||||
showQrcode?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
path: '',
|
||||
showQrcode: true,
|
||||
});
|
||||
|
||||
const copy = () => {
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
<Form path="/addons/hgexample/default" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="websocket" tab="Websocket">
|
||||
<Form path="/socket/hgexample/index/test?name=HotGo" />
|
||||
<Form path="/socket/hgexample/index/test?name=HotGo" :showQrcode="false" />
|
||||
<WebsocketTest />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</n-card>
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Form from './form.vue';
|
||||
import WebsocketTest from './websocketTest.vue';
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
134
web/src/views/addons/hgexample/portal/websocketTest.vue
Normal file
134
web/src/views/addons/hgexample/portal/websocketTest.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="测试websocket">
|
||||
尝试在下方输入框中输入任意文字消息内容,发送后websocket服务器收到会原样返回
|
||||
</n-card>
|
||||
</div>
|
||||
<n-card :bordered="false" class="proCard">
|
||||
<n-space vertical>
|
||||
<n-input-group style="width: 520px">
|
||||
<n-input
|
||||
@keyup.enter="sendMessage"
|
||||
:style="{ width: '78%' }"
|
||||
placeholder="请输入消息内容"
|
||||
:on-focus="onFocus"
|
||||
:on-blur="onBlur"
|
||||
v-model:value="inputMessage"
|
||||
/>
|
||||
<n-button type="primary" @click="sendMessage"> 发送消息</n-button>
|
||||
</n-input-group>
|
||||
|
||||
<div class="mt-5"></div>
|
||||
|
||||
<n-timeline :icon-size="20">
|
||||
<n-timeline-item color="grey" content="输入中.." v-if="isInput">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<MessageOutlined />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-timeline-item>
|
||||
|
||||
<n-timeline-item
|
||||
v-for="item in messages"
|
||||
:key="item"
|
||||
:type="item.type == Enum.SendType ? 'success' : 'info'"
|
||||
:title="item.type == Enum.SendType ? '发送消息' : '收到消息'"
|
||||
:content="item.content"
|
||||
:time="item.time"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<SendOutlined v-if="item.type == Enum.SendType" />
|
||||
<SoundOutlined v-if="item.type == Enum.ReceiveType" />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-timeline-item>
|
||||
</n-timeline>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { MessageOutlined, SendOutlined, SoundOutlined } from '@vicons/antd';
|
||||
import { format } from 'date-fns';
|
||||
import { addOnMessage, removeOnMessage, sendMsg, WebSocketMessage } from '@/utils/websocket';
|
||||
import { useMessage } from 'naive-ui';
|
||||
|
||||
interface Message {
|
||||
type: Enum;
|
||||
content: string;
|
||||
time: string;
|
||||
}
|
||||
|
||||
const message = useMessage();
|
||||
const messages = ref<Message[]>([]);
|
||||
const inputMessage = ref('你好,HotGo');
|
||||
const isInput = ref(false);
|
||||
const testMessageEvent = 'admin/addons/hgexample/testMessage';
|
||||
|
||||
enum Enum {
|
||||
SendType = 1, // 发送类型
|
||||
ReceiveType = 2, // 接受类型
|
||||
}
|
||||
|
||||
function onFocus() {
|
||||
isInput.value = true;
|
||||
}
|
||||
|
||||
function onBlur() {
|
||||
isInput.value = false;
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
if (inputMessage.value == '') {
|
||||
message.error('消息内容不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
sendMsg(testMessageEvent, {
|
||||
message: inputMessage.value,
|
||||
});
|
||||
|
||||
const msg: Message = {
|
||||
type: Enum.SendType,
|
||||
content: inputMessage.value,
|
||||
time: format(new Date(), 'yyyy-MM-dd HH:mm:ss'),
|
||||
};
|
||||
insertMessage(msg);
|
||||
inputMessage.value = '';
|
||||
}
|
||||
|
||||
// 存入本地记录
|
||||
function insertMessage(msg: Message): void {
|
||||
messages.value.unshift(msg); // 在头部插入消息
|
||||
if (messages.value.length > 10) {
|
||||
messages.value = messages.value.slice(0, 10); // 如果超过10个,则只保留最前面10个
|
||||
}
|
||||
}
|
||||
|
||||
const onMessage = (res: WebSocketMessage) => {
|
||||
const msg: Message = {
|
||||
type: Enum.ReceiveType,
|
||||
content: res.data.message,
|
||||
time: format(new Date(), 'yyyy-MM-dd HH:mm:ss'),
|
||||
};
|
||||
insertMessage(msg);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 在当前页面注册消息监听
|
||||
addOnMessage(testMessageEvent, onMessage);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 移除消息监听
|
||||
removeOnMessage(testMessageEvent);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -21,11 +21,11 @@
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
@update:checked-row-keys="onCheckedRow"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
:resizeHeightOffset="-20000"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleUpload">
|
||||
<n-button type="primary" @click="handleUpload" class="ml-2">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<UploadOutlined />
|
||||
@@ -33,26 +33,31 @@
|
||||
</template>
|
||||
上传文件
|
||||
</n-button>
|
||||
|
||||
<n-button type="primary" @click="handleUploadImage">
|
||||
<n-button type="success" @click="handleMultipartUpload" class="ml-2">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<UploadOutlined />
|
||||
<FileAddOutlined />
|
||||
</n-icon>
|
||||
</template>
|
||||
上传大文件
|
||||
</n-button>
|
||||
<n-button type="primary" @click="handleUploadImage" class="ml-2">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<FileImageOutlined />
|
||||
</n-icon>
|
||||
</template>
|
||||
上传图片
|
||||
</n-button>
|
||||
|
||||
<n-button type="primary" @click="handleUploadDoc">
|
||||
<n-button type="primary" @click="handleUploadDoc" class="ml-2">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<UploadOutlined />
|
||||
<FileWordOutlined />
|
||||
</n-icon>
|
||||
</template>
|
||||
上传文档
|
||||
</n-button>
|
||||
|
||||
<n-button type="error" @click="batchDelete" :disabled="batchDeleteDisabled">
|
||||
<n-button type="error" @click="batchDelete" :disabled="batchDeleteDisabled" class="ml-2">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<DeleteOutlined />
|
||||
@@ -67,6 +72,7 @@
|
||||
<FileUpload ref="fileUploadRef" :finish-call="handleFinishCall" />
|
||||
<FileUpload ref="imageUploadRef" :finish-call="handleFinishCall" upload-type="image" />
|
||||
<FileUpload ref="docUploadRef" :finish-call="handleFinishCall" upload-type="doc" />
|
||||
<MultipartUpload ref="multipartUploadRef" @onFinish="handleFinishCall" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -77,8 +83,15 @@
|
||||
import { BasicForm, useForm } from '@/components/Form/index';
|
||||
import { Delete, List } from '@/api/apply/attachment';
|
||||
import { columns, schemas } from './columns';
|
||||
import { DeleteOutlined, UploadOutlined } from '@vicons/antd';
|
||||
import {
|
||||
DeleteOutlined,
|
||||
UploadOutlined,
|
||||
FileWordOutlined,
|
||||
FileImageOutlined,
|
||||
FileAddOutlined,
|
||||
} from '@vicons/antd';
|
||||
import FileUpload from '@/components/FileChooser/src/Upload.vue';
|
||||
import MultipartUpload from '@/components/Upload/multipartUpload.vue';
|
||||
import { Attachment } from '@/components/FileChooser/src/model';
|
||||
|
||||
const message = useMessage();
|
||||
@@ -90,9 +103,10 @@
|
||||
const fileUploadRef = ref();
|
||||
const imageUploadRef = ref();
|
||||
const docUploadRef = ref();
|
||||
const multipartUploadRef = ref();
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 150,
|
||||
width: 120,
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
@@ -132,6 +146,10 @@
|
||||
docUploadRef.value.openModal();
|
||||
}
|
||||
|
||||
function handleMultipartUpload() {
|
||||
multipartUploadRef.value.openModal();
|
||||
}
|
||||
|
||||
const loadDataTable = async (res) => {
|
||||
return await List({ ...res, ...searchFormRef.value?.formModel });
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
@update:checked-row-keys="onCheckedRow"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
:resizeHeightOffset="-20000"
|
||||
>
|
||||
<template #tableTitle>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
:row-key="(row) => row.id"
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="addTable" class="min-left-space">
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
:request="loadDataTable"
|
||||
:row-key="(row) => row.id"
|
||||
ref="actionRef"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
:resizeHeightOffset="-10000"
|
||||
size="small"
|
||||
>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Option } from '@/api/creditsLog';
|
||||
import { isNullObject } from '@/utils/is';
|
||||
import { defRangeShortcuts } from '@/utils/dateUtil';
|
||||
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
|
||||
import {Dicts} from "@/api/dict/dict";
|
||||
|
||||
export interface State {
|
||||
id: number;
|
||||
@@ -240,7 +241,9 @@ export const columns = [
|
||||
];
|
||||
|
||||
async function loadOptions() {
|
||||
options.value = await Option();
|
||||
options.value = await Dicts({
|
||||
types: ['creditType', 'creditGroup'],
|
||||
});
|
||||
for (const item of schemas.value) {
|
||||
switch (item.field) {
|
||||
case 'creditType':
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<n-tab-pane
|
||||
:name="item.key.toString()"
|
||||
:tab="item.label"
|
||||
v-for="item in options.status"
|
||||
v-for="item in options.orderStatus"
|
||||
:key="item.key"
|
||||
>
|
||||
<List :type="defaultTab" />
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
@update:checked-row-keys="onCheckedRow"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
:resizeHeightOffset="-10000"
|
||||
>
|
||||
<template #tableTitle>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Option } from '@/api/order';
|
||||
import { isNullObject } from '@/utils/is';
|
||||
import { defRangeShortcuts } from '@/utils/dateUtil';
|
||||
import { getOptionLabel, getOptionTag, Options } from '@/utils/hotgo';
|
||||
import { Dicts } from '@/api/dict/dict';
|
||||
|
||||
export interface State {
|
||||
id: number;
|
||||
@@ -49,7 +50,7 @@ export function newState(state: State | null): State {
|
||||
}
|
||||
|
||||
export const options = ref<Options>({
|
||||
status: [],
|
||||
orderStatus: [],
|
||||
acceptRefundStatus: [],
|
||||
payType: [],
|
||||
});
|
||||
@@ -170,12 +171,12 @@ export const columns = [
|
||||
style: {
|
||||
marginRight: '6px',
|
||||
},
|
||||
type: getOptionTag(options.value.status, row.status),
|
||||
type: getOptionTag(options.value.orderStatus, row.status),
|
||||
bordered: false,
|
||||
},
|
||||
{
|
||||
default: () =>
|
||||
getOptionLabel(options.value.status, row.status) +
|
||||
getOptionLabel(options.value.orderStatus, row.status) +
|
||||
(row.status === 9 ? ',' + row.rejectRefundReason : ''),
|
||||
}
|
||||
);
|
||||
@@ -190,11 +191,13 @@ export const columns = [
|
||||
];
|
||||
|
||||
async function loadOptions() {
|
||||
options.value = await Option();
|
||||
options.value = await Dicts({
|
||||
types: ['payType', 'orderStatus', 'acceptRefundStatus'],
|
||||
});
|
||||
for (const item of schemas.value) {
|
||||
switch (item.field) {
|
||||
case 'status':
|
||||
item.componentProps.options = options.value.status;
|
||||
item.componentProps.options = options.value.orderStatus;
|
||||
break;
|
||||
case 'acceptRefundStatus':
|
||||
item.componentProps.options = options.value.acceptRefundStatus;
|
||||
|
||||
@@ -23,7 +23,7 @@ export class State {
|
||||
public image = ''; // 单图
|
||||
public attachfile = ''; // 附件
|
||||
public cityId = 0; // 所在城市
|
||||
public switch = 1; // 显示开关
|
||||
public switch = 2; // 显示开关
|
||||
public sort = 0; // 排序
|
||||
public status = 1; // 状态
|
||||
public createdBy = 0; // 创建者
|
||||
@@ -31,7 +31,12 @@ export class State {
|
||||
public createdAt = ''; // 创建时间
|
||||
public updatedAt = ''; // 修改时间
|
||||
public deletedAt = ''; // 删除时间
|
||||
}
|
||||
|
||||
constructor(state?: Partial<State>) {
|
||||
if (state) {
|
||||
Object.assign(this, state);
|
||||
}
|
||||
}}
|
||||
|
||||
export function newState(state: State | Record<string, any> | null): State {
|
||||
if (state !== null) {
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
export const genInfoObj = {
|
||||
label: '',
|
||||
name: '',
|
||||
group: 1,
|
||||
version: 'v1.0.0',
|
||||
brief: '',
|
||||
description: '',
|
||||
author: '',
|
||||
};
|
||||
|
||||
export const selectListObj = {
|
||||
groupType: [],
|
||||
status: [],
|
||||
};
|
||||
|
||||
export function newState(state) {
|
||||
if (state !== null) {
|
||||
return cloneDeep(state);
|
||||
}
|
||||
return cloneDeep(genInfoObj);
|
||||
}
|
||||
@@ -60,7 +60,7 @@
|
||||
>
|
||||
<n-form-item label="插件标签" path="label">
|
||||
<n-input placeholder="请输入" v-model:value="formParams.label" />
|
||||
<template #feedback>显示在插件列表中的标识. 不要超过20个字符</template>
|
||||
<template #feedback>显示在插件列表中的模块名称. 不要超过20个字符</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="插件包名" path="name">
|
||||
@@ -73,12 +73,25 @@
|
||||
<n-form-item label="功能分组" path="group">
|
||||
<n-select
|
||||
placeholder="请选择"
|
||||
:options="selectList.groupType"
|
||||
:options="options.addonsGroupOptions"
|
||||
v-model:value="formParams.group"
|
||||
:on-update:value="onUpdateValueGroup"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="扩展功能" path="extend">
|
||||
<n-checkbox-group v-model:value="formParams.extend">
|
||||
<n-space item-style="display: flex;">
|
||||
<n-checkbox
|
||||
:value="option.value"
|
||||
:label="option.label"
|
||||
v-for="option in options.addonsExtend"
|
||||
:key="option"
|
||||
/>
|
||||
</n-space>
|
||||
</n-checkbox-group>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="版本" path="version">
|
||||
<n-input placeholder="请输入" v-model:value="formParams.version" />
|
||||
<template #feedback>此版本号用于插件的版本更新</template>
|
||||
@@ -114,24 +127,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { h, onBeforeMount, reactive, ref } from 'vue';
|
||||
import {
|
||||
NIcon,
|
||||
NTag,
|
||||
NIconWrapper,
|
||||
useMessage,
|
||||
NImage,
|
||||
useDialog,
|
||||
useNotification,
|
||||
} from 'naive-ui';
|
||||
import { h, reactive, ref } from 'vue';
|
||||
import { NIcon, useMessage, useDialog, useNotification } from 'naive-ui';
|
||||
import { BasicTable, TableAction } from '@/components/Table';
|
||||
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
|
||||
import { List, Selects, Build, UnInstall, Install, Upgrade } from '@/api/develop/addons';
|
||||
import { PlusOutlined } from '@vicons/antd';
|
||||
import { newState } from '@/views/develop/addons/components/model';
|
||||
import { errorImg } from '@/utils/hotgo';
|
||||
import { isUrl } from '@/utils/is';
|
||||
import { getIconComponent } from '@/utils/icons';
|
||||
import { BasicForm, useForm } from '@/components/Form/index';
|
||||
import { List, Build, UnInstall, Install, Upgrade } from '@/api/develop/addons';
|
||||
import { PlusOutlined, QuestionCircleOutlined } from '@vicons/antd';
|
||||
import { newState, schemas, columns, options } from './model';
|
||||
import { adaModalWidth } from '@/utils/hotgo';
|
||||
|
||||
const dialog = useDialog();
|
||||
const message = useMessage();
|
||||
@@ -145,158 +148,6 @@
|
||||
const checkedIds = ref([]);
|
||||
const searchFormRef = ref<any>();
|
||||
|
||||
const selectList = ref({
|
||||
groupType: [],
|
||||
status: [],
|
||||
});
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '图标',
|
||||
key: 'logo',
|
||||
width: 80,
|
||||
render(row) {
|
||||
if (isUrl(row.logo)) {
|
||||
return h(NImage, {
|
||||
width: 48,
|
||||
height: 48,
|
||||
src: row.logo,
|
||||
fallbackSrc: errorImg,
|
||||
style: {
|
||||
width: '48px',
|
||||
height: '48px',
|
||||
'max-width': '100%',
|
||||
'max-height': '100%',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return h(
|
||||
NIconWrapper,
|
||||
{
|
||||
size: 48,
|
||||
borderRadius: 8,
|
||||
},
|
||||
{
|
||||
default: () =>
|
||||
h(
|
||||
NIcon,
|
||||
{
|
||||
size: 36,
|
||||
style: {
|
||||
marginTop: '-8px',
|
||||
},
|
||||
},
|
||||
{
|
||||
default: () => h(getIconComponent(row.logo)),
|
||||
}
|
||||
),
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '模块名称',
|
||||
key: 'name',
|
||||
width: 120,
|
||||
render(row) {
|
||||
return h('div', {
|
||||
innerHTML:
|
||||
'<div >' + row.label + '<br><span style="opacity: 0.8;">' + row.name + '</span></div>',
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '作者',
|
||||
key: 'author',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '分组',
|
||||
key: 'groupName',
|
||||
render(row) {
|
||||
return h(
|
||||
NTag,
|
||||
{
|
||||
style: {
|
||||
marginRight: '6px',
|
||||
},
|
||||
type: 'info',
|
||||
bordered: false,
|
||||
},
|
||||
{
|
||||
default: () => row.groupName,
|
||||
}
|
||||
);
|
||||
},
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '简介',
|
||||
key: 'brief',
|
||||
render(row) {
|
||||
return row.brief;
|
||||
},
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '详细描述',
|
||||
key: 'description',
|
||||
width: 300,
|
||||
render(row) {
|
||||
return h('p', { id: 'app' }, [
|
||||
h('div', {
|
||||
innerHTML: '<div style="white-space: pre-wrap">' + row.description + '</div>',
|
||||
}),
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '版本',
|
||||
key: 'version',
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
|
||||
const schemas = ref<FormSchema[]>([
|
||||
{
|
||||
field: 'name',
|
||||
component: 'NInput',
|
||||
label: '模块名称',
|
||||
componentProps: {
|
||||
placeholder: '请输入模块名称或标签',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
rules: [{ trigger: ['blur'] }],
|
||||
},
|
||||
{
|
||||
field: 'group',
|
||||
component: 'NSelect',
|
||||
label: '分组',
|
||||
componentProps: {
|
||||
placeholder: '请选择分组',
|
||||
options: [],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
component: 'NSelect',
|
||||
label: '安装状态',
|
||||
componentProps: {
|
||||
placeholder: '请选择状态',
|
||||
options: [],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 220,
|
||||
title: '操作',
|
||||
@@ -345,7 +196,7 @@
|
||||
}
|
||||
|
||||
const loadDataTable = async (res) => {
|
||||
mapWidth();
|
||||
adaModalWidth(dialogWidth);
|
||||
return await List({ ...res, ...searchFormRef.value?.formModel });
|
||||
};
|
||||
|
||||
@@ -365,9 +216,6 @@
|
||||
reloadTable();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -383,9 +231,6 @@
|
||||
reloadTable();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -401,9 +246,6 @@
|
||||
reloadTable();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -437,9 +279,6 @@
|
||||
buildSuccessNotify();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
} else {
|
||||
message.error('请填写完整信息');
|
||||
@@ -448,32 +287,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
function mapWidth() {
|
||||
let val = document.body.clientWidth;
|
||||
const def = 840; // 默认宽度
|
||||
if (val < def) {
|
||||
dialogWidth.value = '100%';
|
||||
} else {
|
||||
dialogWidth.value = def + 'px';
|
||||
}
|
||||
|
||||
return dialogWidth.value;
|
||||
}
|
||||
|
||||
const loadSelect = async () => {
|
||||
selectList.value = await Selects({});
|
||||
for (const item of schemas.value) {
|
||||
switch (item.field) {
|
||||
case 'status':
|
||||
item.componentProps.options = selectList.value.status;
|
||||
break;
|
||||
case 'group':
|
||||
item.componentProps.options = selectList.value.groupType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function onUpdateValueGroup(value) {
|
||||
formParams.value.group = value;
|
||||
}
|
||||
@@ -500,10 +313,6 @@
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await loadSelect();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
203
web/src/views/develop/addons/model.ts
Normal file
203
web/src/views/develop/addons/model.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { h, ref } from 'vue';
|
||||
import { Dicts } from '@/api/dict/dict';
|
||||
import { errorImg, Option, Options } from '@/utils/hotgo';
|
||||
import { isUrl } from '@/utils/is';
|
||||
import { NIcon, NIconWrapper, NImage, NTag } from 'naive-ui';
|
||||
import { getIconComponent } from '@/utils/icons';
|
||||
import { FormSchema } from '@/components/Form';
|
||||
|
||||
export const genInfoObj = {
|
||||
label: '',
|
||||
name: '',
|
||||
group: 1,
|
||||
extend: ['resourcePublic', 'resourceTemplate'],
|
||||
version: 'v1.0.0',
|
||||
brief: '',
|
||||
description: '',
|
||||
author: '',
|
||||
};
|
||||
|
||||
export function newState(state) {
|
||||
if (state !== null) {
|
||||
return cloneDeep(state);
|
||||
}
|
||||
return cloneDeep(genInfoObj);
|
||||
}
|
||||
|
||||
export const columns = [
|
||||
{
|
||||
title: '图标',
|
||||
key: 'logo',
|
||||
width: 80,
|
||||
render(row) {
|
||||
if (isUrl(row.logo)) {
|
||||
return h(NImage, {
|
||||
width: 48,
|
||||
height: 48,
|
||||
src: row.logo,
|
||||
fallbackSrc: errorImg,
|
||||
style: {
|
||||
width: '48px',
|
||||
height: '48px',
|
||||
'max-width': '100%',
|
||||
'max-height': '100%',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return h(
|
||||
NIconWrapper,
|
||||
{
|
||||
size: 48,
|
||||
borderRadius: 8,
|
||||
},
|
||||
{
|
||||
default: () =>
|
||||
h(
|
||||
NIcon,
|
||||
{
|
||||
size: 36,
|
||||
style: {
|
||||
marginTop: '-8px',
|
||||
},
|
||||
},
|
||||
{
|
||||
default: () => h(getIconComponent(row.logo)),
|
||||
}
|
||||
),
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '模块名称',
|
||||
key: 'name',
|
||||
width: 120,
|
||||
render(row) {
|
||||
return h('div', {
|
||||
innerHTML:
|
||||
'<div >' + row.label + '<br><span style="opacity: 0.8;">' + row.name + '</span></div>',
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '作者',
|
||||
key: 'author',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '分组',
|
||||
key: 'groupName',
|
||||
render(row) {
|
||||
return h(
|
||||
NTag,
|
||||
{
|
||||
style: {
|
||||
marginRight: '6px',
|
||||
},
|
||||
type: 'info',
|
||||
bordered: false,
|
||||
},
|
||||
{
|
||||
default: () => row.groupName,
|
||||
}
|
||||
);
|
||||
},
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '简介',
|
||||
key: 'brief',
|
||||
render(row) {
|
||||
return row.brief;
|
||||
},
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '详细描述',
|
||||
key: 'description',
|
||||
width: 300,
|
||||
render(row) {
|
||||
return h('p', { id: 'app' }, [
|
||||
h('div', {
|
||||
innerHTML: '<div style="white-space: pre-wrap">' + row.description + '</div>',
|
||||
}),
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '版本',
|
||||
key: 'version',
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
|
||||
export const schemas = ref<FormSchema[]>([
|
||||
{
|
||||
field: 'name',
|
||||
component: 'NInput',
|
||||
label: '模块名称',
|
||||
componentProps: {
|
||||
placeholder: '请输入模块名称或标签',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
rules: [{ trigger: ['blur'] }],
|
||||
},
|
||||
{
|
||||
field: 'group',
|
||||
component: 'NSelect',
|
||||
label: '分组',
|
||||
componentProps: {
|
||||
placeholder: '请选择分组',
|
||||
options: [],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
component: 'NSelect',
|
||||
label: '安装状态',
|
||||
componentProps: {
|
||||
placeholder: '请选择状态',
|
||||
options: [],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
export interface IOptions extends Options {
|
||||
addonsGroupOptions: Option[];
|
||||
addonsInstallStatus: Option[];
|
||||
addonsExtend: Option[];
|
||||
}
|
||||
|
||||
export const options = ref<IOptions>({
|
||||
addonsGroupOptions: [],
|
||||
addonsInstallStatus: [],
|
||||
addonsExtend: [],
|
||||
});
|
||||
|
||||
async function loadOptions() {
|
||||
options.value = await Dicts({
|
||||
types: ['addonsGroupOptions', 'addonsInstallStatus', 'addonsExtend'],
|
||||
});
|
||||
for (const item of schemas.value) {
|
||||
switch (item.field) {
|
||||
case 'status':
|
||||
item.componentProps.options = options.value.addonsInstallStatus;
|
||||
break;
|
||||
case 'group':
|
||||
item.componentProps.options = options.value.addonsGroupOptions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await loadOptions();
|
||||
@@ -42,7 +42,7 @@
|
||||
import { BasicTable } from '@/components/Table';
|
||||
import { genInfoObj, selectListObj } from '@/views/develop/code/components/model';
|
||||
import { ColumnList } from '@/api/develop/code';
|
||||
import { NButton, NCheckbox, NInput, NSelect, NTooltip, NTreeSelect } from 'naive-ui';
|
||||
import { NButton, NCheckbox, NInput, NSelect, NTooltip, NTreeSelect,NCascader } from 'naive-ui';
|
||||
import { HelpCircleOutline, Reload } from '@vicons/ionicons5';
|
||||
import { renderIcon } from '@/utils';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
@@ -278,10 +278,15 @@
|
||||
key: 'dictType',
|
||||
width: 300,
|
||||
render(row) {
|
||||
return h(NTreeSelect, {
|
||||
value: row.dictType,
|
||||
disabled: row.name === 'id',
|
||||
if (row.dictType == 0){
|
||||
row.dictType = null;
|
||||
}
|
||||
return h(NCascader, {
|
||||
placeholder: '请选择字典类型',
|
||||
filterable: true,
|
||||
clearable: true,
|
||||
disabled: row.name === 'id',
|
||||
value: row.dictType,
|
||||
options: props.selectList?.dictMode ?? [],
|
||||
onUpdateValue: function (e) {
|
||||
row.dictType = e;
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
width: 140,
|
||||
},
|
||||
{
|
||||
title: '菜单名称',
|
||||
title: '生成名称',
|
||||
key: 'tableComment',
|
||||
width: 140,
|
||||
},
|
||||
|
||||
@@ -43,6 +43,14 @@
|
||||
loading.value = true;
|
||||
init();
|
||||
});
|
||||
|
||||
function open(src: string) {
|
||||
frameSrc.value = src;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
@update:checked-row-keys="onCheckedRow"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
:resizeHeightOffset="-20000"
|
||||
>
|
||||
<template #tableTitle>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
@update:checked-row-keys="onCheckedRow"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
:resizeHeightOffset="-20000"
|
||||
>
|
||||
<template #tableTitle>
|
||||
@@ -82,7 +82,7 @@
|
||||
const checkedIds = ref([]);
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 150,
|
||||
width: 180,
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
@update:checked-row-keys="onCheckedRow"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="error" @click="batchDelete" :disabled="batchDeleteDisabled">
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
:row-key="(row) => row.id"
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="info" @click="openGroupModal">
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
:row-key="(row) => row.id"
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
/>
|
||||
</n-card>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
:actionColumn="actionColumn"
|
||||
:checked-row-keys="checkedIds"
|
||||
@update:checked-row-keys="onCheckedRow"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
:resizeHeightOffset="-10000"
|
||||
size="small"
|
||||
>
|
||||
@@ -123,7 +123,7 @@
|
||||
const showModal = ref(false);
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 180,
|
||||
width: 150,
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
|
||||
@@ -162,11 +162,11 @@ export const columns = [
|
||||
key: 'content',
|
||||
width: 320,
|
||||
},
|
||||
{
|
||||
title: '调用行',
|
||||
key: 'line',
|
||||
width: 150,
|
||||
},
|
||||
// {
|
||||
// title: '调用行',
|
||||
// key: 'line',
|
||||
// width: 150,
|
||||
// },
|
||||
{
|
||||
title: '触发时间',
|
||||
key: 'triggerNs',
|
||||
|
||||
@@ -93,9 +93,9 @@
|
||||
import DataItem from './components/DataItem.vue';
|
||||
import LoadChart from './components/chart/LoadChart.vue';
|
||||
import FullYearSalesChart from './components/chart/FullYearSalesChart.vue';
|
||||
import { defineComponent, inject, onMounted, ref, onUnmounted } from 'vue';
|
||||
import { defineComponent, onMounted, ref, onUnmounted } from 'vue';
|
||||
import { SocketEnum } from '@/enums/socketEnum';
|
||||
import { addOnMessage, sendMsg } from '@/utils/websocket';
|
||||
import { addOnMessage, removeOnMessage, sendMsg, WebSocketMessage } from '@/utils/websocket';
|
||||
import { formatBefore } from '@/utils/dateUtil';
|
||||
import { useDialog, useMessage } from 'naive-ui';
|
||||
|
||||
@@ -179,35 +179,32 @@
|
||||
const loading = ref(true);
|
||||
const loadChartRef = ref<InstanceType<typeof LoadChart>>();
|
||||
const fullYearSalesChartRef = ref<InstanceType<typeof FullYearSalesChart>>();
|
||||
const onMessageList = inject('onMessageList');
|
||||
|
||||
const onAdminMonitor = (res: { data: string }) => {
|
||||
const data = JSON.parse(res.data);
|
||||
if (data.event === SocketEnum.EventAdminMonitorRunInfo) {
|
||||
loading.value = false;
|
||||
if (data.code == SocketEnum.CodeErr) {
|
||||
message.error('查询出错:' + data.event);
|
||||
return;
|
||||
}
|
||||
|
||||
dataRunInfo.value = data.data;
|
||||
// 运行信息
|
||||
const onMessageAdminMonitorRunInfo = (res: WebSocketMessage) => {
|
||||
loading.value = false;
|
||||
if (res.code == SocketEnum.CodeErr) {
|
||||
message.error('查询出错:' + res.event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.event === SocketEnum.EventAdminMonitorTrends) {
|
||||
loading.value = false;
|
||||
if (data.code == SocketEnum.CodeErr) {
|
||||
message.error('查询出错:' + data.event);
|
||||
return;
|
||||
}
|
||||
dataSource.value = data.data;
|
||||
return;
|
||||
}
|
||||
dataRunInfo.value = res.data;
|
||||
};
|
||||
|
||||
addOnMessage(onMessageList, onAdminMonitor);
|
||||
// 服务器信息
|
||||
const onMessageAdminMonitorTrends = (res: WebSocketMessage) => {
|
||||
loading.value = false;
|
||||
if (res.code == SocketEnum.CodeErr) {
|
||||
message.error('查询出错:' + res.event);
|
||||
return;
|
||||
}
|
||||
dataSource.value = res.data;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
addOnMessage(SocketEnum.EventAdminMonitorRunInfo, onMessageAdminMonitorRunInfo);
|
||||
addOnMessage(SocketEnum.EventAdminMonitorTrends, onMessageAdminMonitorTrends);
|
||||
|
||||
loading.value = true;
|
||||
sendMsg(SocketEnum.EventAdminMonitorTrends);
|
||||
sendMsg(SocketEnum.EventAdminMonitorRunInfo);
|
||||
@@ -231,6 +228,8 @@
|
||||
|
||||
onUnmounted(() => {
|
||||
window.clearInterval(timer.value);
|
||||
removeOnMessage(SocketEnum.EventAdminMonitorTrends);
|
||||
removeOnMessage(SocketEnum.EventAdminMonitorRunInfo);
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
ref="actionRef"
|
||||
:actionColumn="actionColumn"
|
||||
@update:checked-row-keys="onCheckedRow"
|
||||
:scroll-x="1800"
|
||||
:scroll-x="1280"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button
|
||||
@@ -288,7 +288,7 @@
|
||||
});
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 220,
|
||||
width: 240,
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getPostOption } from '@/api/org/post';
|
||||
import { FormSchema, useForm } from '@/components/Form';
|
||||
import { statusOptions } from '@/enums/optionsiEnum';
|
||||
import { defRangeShortcuts } from '@/utils/dateUtil';
|
||||
import {Dicts} from "@/api/dict/dict";
|
||||
|
||||
// 增加余额/积分.
|
||||
|
||||
@@ -213,14 +214,10 @@ export async function loadOptions() {
|
||||
treeDataToCompressed(role.list);
|
||||
}
|
||||
|
||||
const post = await getPostOption();
|
||||
if (post.list && post.list.length > 0) {
|
||||
for (let i = 0; i < post.list.length; i++) {
|
||||
post.list[i].label = post.list[i].name;
|
||||
post.list[i].value = post.list[i].id;
|
||||
}
|
||||
options.value.post = post.list;
|
||||
}
|
||||
const tmpOptions = await Dicts({
|
||||
types: ['adminPostOption'],
|
||||
});
|
||||
options.value.post =tmpOptions?.adminPostOption;
|
||||
}
|
||||
|
||||
function treeDataToCompressed(source) {
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
<template #suffix> MB</template>
|
||||
</n-input-number>
|
||||
</n-form-item>
|
||||
<n-form-item label="图片类型限制" path="uploadImageType">
|
||||
<n-input v-model:value="formValue.uploadImageType" placeholder="" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="文件大小限制" path="uploadFileSize">
|
||||
<n-input-number
|
||||
@@ -39,6 +36,11 @@
|
||||
<template #suffix> MB</template>
|
||||
</n-input-number>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="图片类型限制" path="uploadImageType">
|
||||
<n-input v-model:value="formValue.uploadImageType" placeholder="" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="文件类型限制" path="uploadFileType">
|
||||
<n-input v-model:value="formValue.uploadFileType" placeholder="" />
|
||||
</n-form-item>
|
||||
|
||||
Reference in New Issue
Block a user