mirror of
https://gitee.com/lab1024/smart-admin.git
synced 2025-11-12 13:43:49 +08:00
v3.9.0【优化】typescript版本;【优化】App端消息;【优化】弹出层z-index;
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<!--
|
||||
* 地区选择框
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 15:22:45
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
|
||||
<template>
|
||||
<a-cascader
|
||||
:style="`width:${width}`"
|
||||
v-model:value="areaValue"
|
||||
:show-search="{ filter }"
|
||||
:options="areaOptionData"
|
||||
:placeholder="placeholder"
|
||||
:size="size"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { PROVINCE_CITY_DISTRICT } from './province-city-district';
|
||||
import { PROVINCE_CITY } from './province-city';
|
||||
import { ref, toRaw, watch } from 'vue';
|
||||
|
||||
// ============ 组件属性 ============
|
||||
|
||||
const TYPE_PROVINCE_CITY_DISTRICT = 'province_city_district';
|
||||
|
||||
const props = defineProps({
|
||||
type: String,
|
||||
value: [Number, Array],
|
||||
width: {
|
||||
type: String,
|
||||
default: '200px',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择地区',
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:value', 'change']);
|
||||
|
||||
// ============ 组件业务 ============
|
||||
const areaOptionData = props.type === TYPE_PROVINCE_CITY_DISTRICT ? PROVINCE_CITY_DISTRICT : PROVINCE_CITY;
|
||||
|
||||
// 绑定地区数据
|
||||
const areaValue = ref([]);
|
||||
// 监听value变化
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
let array = [];
|
||||
for (let index = 0; index < 3; index++) {
|
||||
if (newValue[index]) {
|
||||
array.push(newValue[index].value);
|
||||
}
|
||||
}
|
||||
areaValue.value = array;
|
||||
} else {
|
||||
areaValue.value = [];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function handleChange(value, selectedOptions) {
|
||||
emit('update:value', toRaw(selectedOptions));
|
||||
emit('change', value, toRaw(selectedOptions));
|
||||
}
|
||||
|
||||
const filter = (inputValue, path) => {
|
||||
return path.some((option) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
|
||||
};
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,80 @@
|
||||
<!--
|
||||
* 布尔 树形选择组件
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-08-12 21:01:52
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model:value="selectValue"
|
||||
:style="`width: ${width}px`"
|
||||
:placeholder="placeholder"
|
||||
:showSearch="true"
|
||||
:allowClear="true"
|
||||
:size="size"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-select-option v-for="item in $smartEnumPlugin.getValueDescList('FLAG_NUMBER_ENUM')" :key="item.value" :value="item.value">
|
||||
{{ item.desc }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from 'lodash';
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
value: Number,
|
||||
width: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择',
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:value', 'change']);
|
||||
|
||||
function convertBoolean2number(value) {
|
||||
let result = null;
|
||||
if (_.isNaN(value) || _.isNull(value) || _.isUndefined(value)) {
|
||||
result = null;
|
||||
} else {
|
||||
result = value ? 1 : 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// 箭头value变化
|
||||
const selectValue = ref(convertBoolean2number(props.value));
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = convertBoolean2number(newValue);
|
||||
}
|
||||
);
|
||||
|
||||
const handleChange = (value) => {
|
||||
console.log('boolean enum select', value);
|
||||
let booleanResult = null;
|
||||
if (!_.isUndefined(value)) {
|
||||
booleanResult = value === 1;
|
||||
}
|
||||
emit('update:value', booleanResult);
|
||||
emit('change', booleanResult);
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,133 @@
|
||||
<!--
|
||||
* 图标 选择
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-01 23:14:49
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<a-popover v-model:open="visible" placement="bottomLeft" trigger="click">
|
||||
<template #title>
|
||||
<a-form-item>
|
||||
<a-radio-group @change="updateSelectIconArray" v-model:value="iconStyle" style="margin: 8px">
|
||||
<a-radio-button value="outlined">线框风格</a-radio-button>
|
||||
<a-radio-button value="filled">实底风格</a-radio-button>
|
||||
<a-radio-button value="twoTone">双色风格</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-input-search v-model:value="searchValue" placeholder="输入英文关键词进行搜索" @change="updateSelectIconArray" />
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<div class="icon-box">
|
||||
<div v-for="item in iconLoopArray" :key="item" @click="handleClick(item)" class="icon-content">
|
||||
<component :is="$antIcons[item]" />
|
||||
</div>
|
||||
<div v-show="showMoreIndex > 0">
|
||||
<a-button type="link" @click="showMore">点击展开更多图标(因图标较多,可能会卡一小会)</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<slot name="iconSelect"></slot>
|
||||
</a-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as VueIcon from '@ant-design/icons-vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
//线框风格图标数组
|
||||
const outlinedIconArray = Object.keys(VueIcon).filter((e) => _.endsWith(e.toLowerCase(), 'outlined'));
|
||||
//实底风格图标数组
|
||||
const filledIconArray = Object.keys(VueIcon).filter((e) => _.endsWith(e.toLowerCase(), 'filled'));
|
||||
//双色风格图标数组
|
||||
const twoToneIconArray = Object.keys(VueIcon).filter((e) => _.endsWith(e.toLowerCase(), 'twotone'));
|
||||
|
||||
// ------------ 显示/隐藏 ------------
|
||||
const visible = ref(false);
|
||||
|
||||
// ------------ 展开更多 ------------
|
||||
const SHOW_MORE_LENGTH = 35;
|
||||
const showMoreIndex = ref(SHOW_MORE_LENGTH);
|
||||
function showMore() {
|
||||
showMoreIndex.value = -1;
|
||||
}
|
||||
|
||||
// ------------ 图标展示与搜索 ------------
|
||||
|
||||
const iconStyle = ref('outlined');
|
||||
const selectIconArray = ref([...outlinedIconArray]);
|
||||
|
||||
const iconLoopArray = computed(() => {
|
||||
return _.slice(selectIconArray.value, 0, showMoreIndex.value);
|
||||
});
|
||||
|
||||
watch(iconStyle, (newValue, oldValue) => {
|
||||
updateSelectIconArray();
|
||||
});
|
||||
|
||||
let searchValue = ref('');
|
||||
function updateSelectIconArray() {
|
||||
let tempArray = null;
|
||||
if (iconStyle.value === 'outlined') {
|
||||
tempArray = outlinedIconArray;
|
||||
} else if (iconStyle.value === 'filled') {
|
||||
tempArray = filledIconArray;
|
||||
} else {
|
||||
tempArray = twoToneIconArray;
|
||||
}
|
||||
if (!searchValue.value) {
|
||||
selectIconArray.value = tempArray;
|
||||
} else {
|
||||
selectIconArray.value = tempArray.filter((e) => e.toLowerCase().includes(searchValue.value.toLowerCase()));
|
||||
}
|
||||
|
||||
if (selectIconArray.value.length > SHOW_MORE_LENGTH) {
|
||||
showMoreIndex.value = SHOW_MORE_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------ 对外抛出选择图标事件 ------------
|
||||
const emit = defineEmits(['updateIcon']);
|
||||
function handleClick(icon) {
|
||||
visible.value = false;
|
||||
emit('updateIcon', icon);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.icon-box {
|
||||
overflow: auto;
|
||||
font-size: 20px;
|
||||
width: 410px;
|
||||
height: 300px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.icon-content {
|
||||
width: 45px;
|
||||
height: 40px;
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #ccc;
|
||||
.more-icon {
|
||||
font-size: 14px;
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
.icon-content:hover {
|
||||
background: #1890ff;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
* iframe 组件
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-01 23:14:49
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
-->
|
||||
<template>
|
||||
<iframe :id="name" :src="url" frameborder="0" height="800" scrolling="yes" width="100%"></iframe>
|
||||
</template>
|
||||
<script setup>
|
||||
let props = defineProps({
|
||||
name: String,
|
||||
url: String,
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
@@ -0,0 +1,55 @@
|
||||
<!--
|
||||
* 枚举 多选框
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-08-08 20:32:30
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<a-checkbox-group :style="`width: ${width}`" v-model:value="selectValue" :options="optionList" @change="handleChange" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, getCurrentInstance, onMounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
enumName: String,
|
||||
value: Array,
|
||||
width: {
|
||||
type: String,
|
||||
default: '200px',
|
||||
},
|
||||
});
|
||||
|
||||
// ------------ 枚举数据 加载和构建 ------------
|
||||
|
||||
const optionList = ref([]);
|
||||
function buildOptionList() {
|
||||
const internalInstance = getCurrentInstance(); // 有效 全局
|
||||
const smartEnumPlugin = internalInstance.appContext.config.globalProperties.$smartEnumPlugin;
|
||||
const valueList = smartEnumPlugin.getValueDescList(props.enumName);
|
||||
optionList.value = valueList.map((e) => Object.assign({}, { value: e.value, label: e.desc }));
|
||||
}
|
||||
|
||||
onMounted(buildOptionList);
|
||||
|
||||
// ------------ 数据选中 事件及其相关 ------------
|
||||
|
||||
const selectValue = ref(props.value);
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(['update:value', 'change']);
|
||||
function handleChange(value) {
|
||||
emit('update:value', value);
|
||||
emit('change', value);
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,63 @@
|
||||
<!--
|
||||
* 枚举 radio
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-08-08 20:32:30
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<template v-if="isButton">
|
||||
<a-radio-group v-model:value="selectValue" @change="handleChange" button-style="solid">
|
||||
<a-radio-button v-for="item in $smartEnumPlugin.getValueDescList(props.enumName)" :key="item.value" :value="item.value">
|
||||
{{ item.desc }}
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-radio-group v-model:value="selectValue" @change="handleChange">
|
||||
<a-radio v-for="item in $smartEnumPlugin.getValueDescList(props.enumName)" :key="item.value" :value="item.value">
|
||||
{{ item.desc }}
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
enumName: String,
|
||||
value: [Number, String],
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%',
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
isButton: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:value', 'change']);
|
||||
|
||||
const selectValue = ref(props.value);
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
function handleChange(e) {
|
||||
emit('update:value', e.target.value);
|
||||
emit('change', e.target.value);
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!--
|
||||
* 枚举 下拉框
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-08-08 20:32:30
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model:value="selectValue"
|
||||
:style="`width: ${width}`"
|
||||
:placeholder="props.placeholder"
|
||||
:showSearch="true"
|
||||
:allowClear="true"
|
||||
:size="size"
|
||||
@change="handleChange"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<a-select-option v-for="item in $smartEnumPlugin.getValueDescList(props.enumName)" :key="item.value" :value="item.value">
|
||||
{{ item.desc }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
enumName: String,
|
||||
value: [Number,String],
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择',
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:value', 'change']);
|
||||
|
||||
const selectValue = ref(props.value);
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
function handleChange(value) {
|
||||
emit('update:value', value);
|
||||
emit('change', value);
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* loading 组件
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-07-22 20:33:41
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*/
|
||||
import { useSpinStore } from "/@/store/modules/system/spin";
|
||||
|
||||
export const SmartLoading = {
|
||||
show: () => {
|
||||
useSpinStore().show();
|
||||
},
|
||||
|
||||
hide: () => {
|
||||
useSpinStore().hide();
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
<!--
|
||||
* 编辑器
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 15:34:33
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<div style="border: 1px solid #ccc">
|
||||
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" />
|
||||
<Editor
|
||||
style="overflow-y: hidden"
|
||||
:style="{ height: `${height}px` }"
|
||||
v-model="editorHtml"
|
||||
:defaultConfig="editorConfig"
|
||||
@onCreated="handleCreated"
|
||||
@onChange="handleChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { shallowRef, onBeforeUnmount, watch, ref } from 'vue';
|
||||
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';
|
||||
import { fileApi } from '/@/api/support/file-api';
|
||||
import '@wangeditor/editor/dist/css/style.css';
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
||||
import { smartSentry } from '/@/lib/smart-sentry';
|
||||
|
||||
//菜单
|
||||
const editorConfig = { MENU_CONF: {} };
|
||||
|
||||
//上传
|
||||
let customUpload = {
|
||||
async customUpload(file, insertFn) {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
let res = await fileApi.uploadFile(formData, FILE_FOLDER_TYPE_ENUM.COMMON.value);
|
||||
let data = res.data;
|
||||
insertFn(data.fileUrl);
|
||||
} catch (error) {
|
||||
smartSentry.captureError(error);
|
||||
}
|
||||
},
|
||||
};
|
||||
editorConfig.MENU_CONF['uploadImage'] = customUpload;
|
||||
editorConfig.MENU_CONF['uploadVideo'] = customUpload;
|
||||
|
||||
// ----------------------- 以下是公用变量 emits props ----------------
|
||||
const editorHtml = ref();
|
||||
let props = defineProps({
|
||||
modelValue: String,
|
||||
height: {
|
||||
type: Number,
|
||||
default: 500,
|
||||
},
|
||||
});
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(nVal) => {
|
||||
editorHtml.value = nVal;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
|
||||
// 获取编辑器实例html
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const editorRef = shallowRef();
|
||||
const handleCreated = (editor) => {
|
||||
editorRef.value = editor;
|
||||
};
|
||||
const handleChange = (editor) => {
|
||||
emit('update:modelValue', editorHtml.value);
|
||||
};
|
||||
|
||||
function getHtml() {
|
||||
const htmlContent = editorRef.value.getHtml();
|
||||
return htmlContent === '<p><br></p>' ? '' : htmlContent;
|
||||
}
|
||||
function getText() {
|
||||
return editorRef.value.getText();
|
||||
}
|
||||
|
||||
// 组件销毁时,也及时销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
const editor = editorRef.value;
|
||||
if (editor == null) return;
|
||||
editor.destroy();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
editorRef,
|
||||
getHtml,
|
||||
getText,
|
||||
});
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
.w-e-full-screen-container {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user