提交代码
This commit is contained in:
307
src/components/MyComponents/AddressSelect/index.vue
Normal file
307
src/components/MyComponents/AddressSelect/index.vue
Normal file
@ -0,0 +1,307 @@
|
||||
<template>
|
||||
<div class="form-item-box zj-addressSelect-wrap" :style="{ width: width }">
|
||||
<el-select :placeholder="placeholder" :clearable="true" v-model="value" popper-class="adderss-select"
|
||||
@clear="handleClear">
|
||||
<el-option value="1" style="display: none"></el-option>
|
||||
<el-input v-if="filterable" v-model="filterText" style="margin-bottom: 5px; font-size: 12px"
|
||||
:prefix-icon="Search" />
|
||||
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
|
||||
<el-tab-pane name="province" :label="province ? province : '请选择'">
|
||||
<div class="citylist">
|
||||
<ul>
|
||||
<li @click="chooseProvince(item)" v-for="item in provinceList" :key="item.code"
|
||||
:class="{ selected: provinceId == item.code }">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="city" v-if="cityList.length > 0" :label="city ? city : '请选择'">
|
||||
<div class="citylist">
|
||||
<ul>
|
||||
<li @click="chooseCity(item)" v-for="item in cityList" :class="{ selected: cityId == item.code }"
|
||||
:key="item.code">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="area" v-if="areaList.length > 0" :label="area ? area : '请选择'">
|
||||
<div class="citylist">
|
||||
<ul>
|
||||
<li @click="chooseArea(item)" v-for="item in areaList" :key="item.code"
|
||||
:class="{ selected: areaId == item.code }">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="street" v-if="streetList.length > 0" :label="street ? street : '请选择'">
|
||||
<div class="citylist">
|
||||
<ul>
|
||||
<li @click="chooseStreet(item)" v-for="item in streetList" :key="item.code"
|
||||
:class="{ selected: streetId == item.code }">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-select>
|
||||
<!-- <el-icon class="errorIcon">
|
||||
<circle-close-filled />
|
||||
</el-icon>
|
||||
<el-icon class="checkIcon">
|
||||
<circle-check-filled />
|
||||
</el-icon> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from '@/constant';
|
||||
import { nextTick, ref, watch } from "vue";
|
||||
import { Search } from "@element-plus/icons-vue";
|
||||
const emits = defineEmits(["handleChange"]); //子组件向父组件事件传递
|
||||
const props = defineProps({
|
||||
placeholder: {
|
||||
default: "选择地址",
|
||||
type: String
|
||||
},
|
||||
filterable: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
address: {
|
||||
default: () => [],
|
||||
type: Array
|
||||
},
|
||||
defaultConf: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
children: "",
|
||||
label: "",
|
||||
id: ""
|
||||
})
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
const filterText = ref("");
|
||||
const activeName = ref("province");
|
||||
const value = ref("");
|
||||
const valueId = ref([]);
|
||||
const province = ref("");
|
||||
const provinceId = ref("");
|
||||
const provinceList = ref([]);
|
||||
provinceList.value = require("@/constant/pca-code.json");
|
||||
const city = ref("");
|
||||
const cityId = ref("");
|
||||
const cityList = ref([]);
|
||||
const area = ref("");
|
||||
const areaId = ref("");
|
||||
const areaList = ref([]);
|
||||
const street = ref("");
|
||||
const streetId = ref("");
|
||||
const streetList = ref([]);
|
||||
const provinceListFilter = ref([]);
|
||||
provinceListFilter.value = require("@/constant/pca-code.json");
|
||||
const cityListFilter = ref([]);
|
||||
const areaListFilter = ref([]);
|
||||
const streetListFilter = ref([]);
|
||||
nextTick(() => {
|
||||
if (props.address.length > 0) {
|
||||
init(props.address);
|
||||
}
|
||||
});
|
||||
watch(filterText, (val) => {
|
||||
filterNode(val);
|
||||
});
|
||||
const handleClick = () => {
|
||||
filterText.value = "";
|
||||
filterNode("");
|
||||
};
|
||||
const filterNode = (val) => {
|
||||
if (activeName.value === "province") {
|
||||
if (val !== "") {
|
||||
provinceList.value = provinceListFilter.value.filter(
|
||||
(item) => item[props.defaultConf.label].indexOf(val) !== -1
|
||||
);
|
||||
} else {
|
||||
provinceList.value = provinceListFilter.value;
|
||||
}
|
||||
} else if (activeName.value === "city") {
|
||||
if (val !== "") {
|
||||
cityList.value = cityListFilter.value.filter(
|
||||
(item) => item[props.defaultConf.label].indexOf(val) !== -1
|
||||
);
|
||||
} else {
|
||||
cityList.value = cityListFilter.value;
|
||||
}
|
||||
} else if (activeName.value === "area") {
|
||||
if (val !== "") {
|
||||
areaList.value = areaListFilter.value.filter(
|
||||
(item) => item[props.defaultConf.label].indexOf(val) !== -1
|
||||
);
|
||||
} else {
|
||||
areaList.value = areaListFilter.value;
|
||||
}
|
||||
} else if (activeName.value === "street") {
|
||||
if (val !== "") {
|
||||
streetList.value = streetListFilter.value.filter(
|
||||
(item) => item[props.defaultConf.label].indexOf(val) !== -1
|
||||
);
|
||||
} else {
|
||||
streetList.value = streetListFilter.value;
|
||||
}
|
||||
}
|
||||
};
|
||||
const chooseProvince = (e) => {
|
||||
province.value = e[props.defaultConf.label];
|
||||
provinceId.value = e[props.defaultConf.id];
|
||||
value.value = province.value;
|
||||
valueId.value = [provinceId.value];
|
||||
emits("handleChange", valueId.value);
|
||||
city.value = "";
|
||||
cityId.value = "";
|
||||
cityList.value = [];
|
||||
areaList.value = [];
|
||||
streetList.value = [];
|
||||
filterText.value = "";
|
||||
provinceList.value.forEach((el) => {
|
||||
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
|
||||
if (el[props.defaultConf.children]) {
|
||||
activeName.value = "city";
|
||||
cityList.value = el[props.defaultConf.children];
|
||||
cityListFilter.value = el[props.defaultConf.children];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const chooseCity = (e) => {
|
||||
city.value = e[props.defaultConf.label];
|
||||
cityId.value = e[props.defaultConf.id];
|
||||
area.value = "";
|
||||
areaId.value = "";
|
||||
areaList.value = [];
|
||||
streetList.value = [];
|
||||
filterText.value = "";
|
||||
value.value = province.value + "/" + city.value;
|
||||
valueId.value = [provinceId.value, cityId.value];
|
||||
emits("handleChange", valueId.value);
|
||||
cityList.value.forEach((el) => {
|
||||
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
|
||||
if (el[props.defaultConf.children]) {
|
||||
activeName.value = "area";
|
||||
areaList.value = el[props.defaultConf.children];
|
||||
areaListFilter.value = el[props.defaultConf.children];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const chooseArea = (e) => {
|
||||
area.value = e[props.defaultConf.label];
|
||||
areaId.value = e[props.defaultConf.id];
|
||||
street.value = "";
|
||||
streetId.value = "";
|
||||
streetList.value = [];
|
||||
filterText.value = "";
|
||||
value.value = province.value + "/" + city.value + "/" + area.value;
|
||||
valueId.value = [provinceId.value, cityId.value, areaId.value];
|
||||
emits("handleChange", valueId.value);
|
||||
areaList.value.forEach((el) => {
|
||||
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
|
||||
if (el[props.defaultConf.children]) {
|
||||
streetList.value = el[props.defaultConf.children];
|
||||
activeName.value = "street";
|
||||
streetListFilter.value = el[props.defaultConf.children];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const chooseStreet = (e) => {
|
||||
street.value = e[props.defaultConf.label];
|
||||
streetId.value = e[props.defaultConf.id];
|
||||
value.value =
|
||||
province.value + "/" + city.value + "/" + area.value + "/" + street.value;
|
||||
valueId.value = [
|
||||
provinceId.value,
|
||||
cityId.value,
|
||||
areaId.value,
|
||||
streetId.value
|
||||
];
|
||||
emits("handleChange", valueId.value);
|
||||
};
|
||||
const handleClear = () => {
|
||||
activeName.value = "province";
|
||||
value.value = "";
|
||||
valueId.value = [];
|
||||
province.value = "";
|
||||
provinceId.value = "";
|
||||
city.value = "";
|
||||
cityId.value = "";
|
||||
cityList.value = [];
|
||||
area.value = "";
|
||||
areaId.value = "";
|
||||
areaList.value = [];
|
||||
street.value = "";
|
||||
streetId.value = "";
|
||||
streetList.value = [];
|
||||
cityListFilter.value = [];
|
||||
areaListFilter.value = [];
|
||||
streetListFilter.value = [];
|
||||
filterText.value = "";
|
||||
filterNode("");
|
||||
emits("handleChange", []);
|
||||
};
|
||||
const treeValueFind = (tree, arr, newArr = []) => {
|
||||
tree.forEach((el) => {
|
||||
if (el[props.defaultConf.id] === arr) {
|
||||
newArr.push(el);
|
||||
}
|
||||
if (el[props.defaultConf.children]) {
|
||||
treeValueFind(el[props.defaultConf.children], arr, newArr);
|
||||
}
|
||||
});
|
||||
return newArr;
|
||||
};
|
||||
const init = (data) => {
|
||||
let obj1 = treeValueFind(provinceList.value, data[0])[0];
|
||||
province.value = obj1[props.defaultConf.label];
|
||||
provinceId.value = obj1[props.defaultConf.id];
|
||||
cityList.value = obj1[props.defaultConf.children];
|
||||
cityListFilter.value = obj1[props.defaultConf.children];
|
||||
value.value = province.value;
|
||||
if (data[1]) {
|
||||
let obj2 = treeValueFind(provinceList.value, data[1])[0];
|
||||
city.value = obj2[props.defaultConf.label];
|
||||
cityId.value = obj2[props.defaultConf.id];
|
||||
areaList.value = obj2[props.defaultConf.children];
|
||||
areaListFilter.value = obj2[props.defaultConf.children];
|
||||
value.value = province.value + "/" + city.value;
|
||||
}
|
||||
if (data[2]) {
|
||||
let obj3 = treeValueFind(provinceList.value, data[2])[0];
|
||||
area.value = obj3[props.defaultConf.label];
|
||||
areaId.value = obj3[props.defaultConf.id];
|
||||
streetList.value = obj3[props.defaultConf.children];
|
||||
streetListFilter.value = obj3[props.defaultConf.children];
|
||||
value.value = province.value + "/" + city.value + "/" + area.value;
|
||||
}
|
||||
if (data[3]) {
|
||||
let obj4 = treeValueFind(provinceList.value, data[3])[0];
|
||||
street.value = obj4[props.defaultConf.label];
|
||||
streetId.value = obj4[props.defaultConf.id];
|
||||
value.value =
|
||||
province.value + "/" + city.value + "/" + area.value + "/" + street.value;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.zj-addressSelect-wrap {
|
||||
::v-deep .el-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
88
src/components/MyComponents/ChooseIcon/index.vue
Normal file
88
src/components/MyComponents/ChooseIcon/index.vue
Normal file
@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<!--选择图标-->
|
||||
<div class="form-item-box choose-icon-zj" :style="{ width: width }">
|
||||
<el-autocomplete v-bind="$attrs" v-model="modelValue" :fetch-suggestions="querySearch"
|
||||
popper-class="choose-icon-zj-autocomplete" :placeholder="placeholder" @change="onInput" @select="handleSelect">
|
||||
<template #prefix>
|
||||
<SvgIcon :icon="modelValue"></SvgIcon>
|
||||
</template>
|
||||
<template #default="{ item }">
|
||||
<SvgIcon :icon="item.link"></SvgIcon>
|
||||
<div class="value">{{ item.value }}</div>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
<!-- <el-icon class="errorIcon">
|
||||
<circle-close-filled />
|
||||
</el-icon>
|
||||
<el-icon class="checkIcon">
|
||||
<circle-check-filled />
|
||||
</el-icon> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from "@/constant";
|
||||
import { ref, defineProps, defineEmits, defineExpose, onMounted } from "vue";
|
||||
const props = defineProps({
|
||||
placeholder: {
|
||||
default: "请输入图标名称",
|
||||
type: String
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
const links = ref([]);
|
||||
|
||||
const querySearch = (queryString, cb) => {
|
||||
const results = queryString
|
||||
? links.value.filter(createFilter(queryString))
|
||||
: links.value;
|
||||
cb(results);
|
||||
};
|
||||
const createFilter = (queryString) => {
|
||||
return (restaurant) => {
|
||||
return (
|
||||
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
const handleSelect = (item) => {
|
||||
emits("update:modelValue", item.value);
|
||||
};
|
||||
|
||||
const handleIconClick = (ev) => {
|
||||
};
|
||||
|
||||
const loadAll = () => {
|
||||
const svgRequire = require.context("@/icons/svg", false, /\.svg$/);
|
||||
const re = svgRequire.keys().map((svgIcon) => {
|
||||
const iconName = svgIcon.split("/")[1];
|
||||
const prefixIconName = iconName.split(".")[0];
|
||||
return { value: prefixIconName, link: prefixIconName };
|
||||
});
|
||||
return re;
|
||||
};
|
||||
const iconListShow = ref(false);
|
||||
const showIconList = () => {
|
||||
iconListShow.value = true;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
links.value = loadAll();
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const onInput = (e) => {
|
||||
emits("update:modelValue", e);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
32
src/components/MyComponents/Date/index.vue
Normal file
32
src/components/MyComponents/Date/index.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="form-item-box" :style="{ width: width }">
|
||||
<el-date-picker style="width:100%" v-model="modelValue" type="date" v-bind="$attrs" @change="onInput" :placeholder="placeholder" value-format="YYYY-MM-DD"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from "@/constant";
|
||||
import { ref, defineProps, defineEmits, defineExpose } from "vue";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请填写",
|
||||
type: String
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const onInput = (e) => {
|
||||
emits("update:modelValue", e);
|
||||
};
|
||||
</script>
|
||||
|
119
src/components/MyComponents/Department/index.vue
Normal file
119
src/components/MyComponents/Department/index.vue
Normal file
@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="form-item-box" :style="{ width: width }">
|
||||
<el-cascader
|
||||
style="width: 100%"
|
||||
class="el-cascader-zj"
|
||||
:show-all-levels="false"
|
||||
clearable
|
||||
filterable
|
||||
:placeholder="modelValue ? placeholder : '请选择部门'"
|
||||
:options="tableData"
|
||||
v-model="oldmodelValue"
|
||||
@change="handleChange"
|
||||
:props="endProps"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from "@/constant";
|
||||
import { qcckPost, qcckGet, qcckFlvGet } from "@/api/qcckApi.js";
|
||||
import {
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
defineExpose,
|
||||
computed,
|
||||
onMounted,
|
||||
watch
|
||||
} from "vue";
|
||||
import { selectDeptPage } from "@/api/user-manage";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请选择",
|
||||
type: String
|
||||
},
|
||||
multiple: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
isAll: {
|
||||
default: 100,
|
||||
type: Number
|
||||
},
|
||||
modelValue: {
|
||||
type: Array || String,
|
||||
default: []
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
const modelShow = ref(false);
|
||||
const oldmodelValue = ref([]);
|
||||
const listQuery = ref({
|
||||
deptname: "",
|
||||
deptcode: "",
|
||||
parentid: ""
|
||||
});
|
||||
const depList = ref([])
|
||||
//配置项
|
||||
const endProps = {
|
||||
children: "childDeptList",
|
||||
value: "orgCode",
|
||||
label: "orgName",
|
||||
checkStrictly: true,
|
||||
multiple: props.multiple,
|
||||
lazy: true,
|
||||
lazyLoad(node, resolve) {
|
||||
listQuery.value.parentid = node.data.id;
|
||||
selectDeptPage(listQuery.value).then((res) => {
|
||||
depList.value = depList.value.concat(res)
|
||||
//处理部门是否包含下级
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
res[i].leaf = !res[i].hasChildren;
|
||||
}
|
||||
resolve(res);
|
||||
});
|
||||
}
|
||||
};
|
||||
const tableData = ref([]);
|
||||
const getSysMenuTree = async () => {
|
||||
const res = await selectDeptPage(listQuery.value);
|
||||
tableData.value = res;
|
||||
depList.value = res
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getSysMenuTree();
|
||||
});
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
console.log(val,'val');
|
||||
oldmodelValue.value = val;
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
const emits = defineEmits(["update:modelValue",'getDepValue']);
|
||||
const handleChange = (e) => {
|
||||
console.log(e,'e');
|
||||
if (props.multiple === true) {
|
||||
const data = e.map((item) => {return item[item.length - 1];});
|
||||
emits("update:modelValue", data);
|
||||
} else {
|
||||
const data = e ? e[e.length - 1] : "";
|
||||
emits("update:modelValue", data);
|
||||
let obj = depList.value.find(item=>{ return item.orgCode == data})
|
||||
emits("getDepValue", obj);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-cascader-zj {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
158
src/components/MyComponents/DepartmentTree/index.vue
Normal file
158
src/components/MyComponents/DepartmentTree/index.vue
Normal file
@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div class="departmentTree-box" :style="{ width: width, height: '100%' }">
|
||||
<div class="depar_hear">
|
||||
<el-input
|
||||
v-model="listQuery.deptname"
|
||||
v-if="filterable"
|
||||
clearable
|
||||
:debounce="500"
|
||||
@input="filterTextChange"
|
||||
placeholder="请输入筛选条件"
|
||||
/>
|
||||
</div>
|
||||
<div class="depar_foot">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
class="filter-tree"
|
||||
:props="endProps"
|
||||
lazy
|
||||
:load="loadNode"
|
||||
@node-click="nodeClick"
|
||||
:filter-node-method="filterNode"
|
||||
:data="treeData"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { debounce } from "lodash";
|
||||
import { getItem } from "@/utils/storage";
|
||||
import { COMPONENT_WIDTH } from "@/constant";
|
||||
import { ref, defineProps, defineEmits, watch, computed, onMounted } from "vue";
|
||||
import { selectDeptPage, getAllChildDeptList } from "@/api/user-manage";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请选择",
|
||||
type: String
|
||||
},
|
||||
multiple: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
filterable: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
modelValue: {
|
||||
type: Number
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
},
|
||||
isBmId:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
});
|
||||
const listQuery = ref({
|
||||
deptname: "",
|
||||
deptcode: "",
|
||||
parentid: ""
|
||||
});
|
||||
const treeRef = ref(null);
|
||||
const node_had = ref([]);
|
||||
const resolve_had = ref([]);
|
||||
//防抖处理
|
||||
const filterTextChange = debounce(inputChange, 500);
|
||||
onMounted(() => {});
|
||||
//获取部门数据
|
||||
function getTreeData() {
|
||||
selectDeptPage(listQuery.value).then((res) => {
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
res[i].leaf = !res[i].hasChildren;
|
||||
}
|
||||
treeData.value = res;
|
||||
});
|
||||
}
|
||||
//搜索查询
|
||||
function inputChange(e) {
|
||||
selectDeptPage(listQuery.value).then((res) => {
|
||||
treeData.value = res;
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => listQuery.value.deptname,
|
||||
(val) => {
|
||||
treeRef.value.filter("tree", val);
|
||||
}
|
||||
);
|
||||
const endProps = {
|
||||
children: "childDeptList",
|
||||
value: "id",
|
||||
label: "orgName",
|
||||
isLeaf: "leaf"
|
||||
};
|
||||
const treeData = ref([]);
|
||||
//懒加载方法
|
||||
async function loadNode(node, resolve) {
|
||||
listQuery.value.parentid = node.data.id;
|
||||
if (node.level === 0) {
|
||||
node_had.value = node;
|
||||
resolve_had.value = resolve;
|
||||
getTreeData();
|
||||
}
|
||||
if (node.level >= 1) {
|
||||
selectDeptPage(listQuery.value).then((res) => {
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
res[i].leaf = !res[i].hasChildren;
|
||||
}
|
||||
resolve(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
const filterNode = (value, data) => {
|
||||
if (!value) return true;
|
||||
return data.orgName.includes(value);
|
||||
};
|
||||
|
||||
const nodeClick = (node) => {
|
||||
if(props.isBmId){
|
||||
emits("update:modelValue", node.id);
|
||||
}else{
|
||||
emits("update:modelValue", node.orgCode);
|
||||
}
|
||||
};
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const handleChange = (e) => {
|
||||
if (props.multiple === true) {
|
||||
const data = e.map((item) => {
|
||||
return item[item.length - 1];
|
||||
});
|
||||
emits("update:modelValue", data);
|
||||
} else {
|
||||
const data = e[0];
|
||||
emits("update:modelValue", data);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.depar_hear {
|
||||
height: 32px;
|
||||
}
|
||||
.depar_foot {
|
||||
height: calc(100% - 32px);
|
||||
overflow: auto;
|
||||
width: 280px;
|
||||
width: 100%;
|
||||
min-width: 300px;
|
||||
}
|
||||
.departmentTree-box {
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
88
src/components/MyComponents/DownLoad/index.vue
Normal file
88
src/components/MyComponents/DownLoad/index.vue
Normal file
@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="导出预览"
|
||||
width="1400px"
|
||||
:model-value="modelValue"
|
||||
@close="closed"
|
||||
>
|
||||
<el-table :data="data" :id="myId" style="width: 100%" border>
|
||||
<el-table-column label="序号" type="index" align="center" width="80" />
|
||||
<el-table-column
|
||||
v-for="(item, index) in tabOption"
|
||||
:key="index + 'tab'"
|
||||
:prop="item.prop"
|
||||
:label="item.label"
|
||||
align="center"
|
||||
>
|
||||
<template v-if="item.dict" #default="{ row }">
|
||||
<dict-tag :options="item.dict" :value="row[item.prop]" :tag="false" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="closed">取消</el-button>
|
||||
<el-button type="primary" @click="exportExcel">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, ref, onMounted, getCurrentInstance } from "vue";
|
||||
import FileSaver from "file-saver";
|
||||
import * as XLSX from "xlsx";
|
||||
const tabRef = ref(null);
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
tabOption: {
|
||||
type: Array,
|
||||
require: []
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
required: []
|
||||
},
|
||||
myId: {
|
||||
type: String,
|
||||
require: ""
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
require: ""
|
||||
}
|
||||
});
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const closed = () => {
|
||||
emits("update:modelValue", false);
|
||||
};
|
||||
const { proxy } = getCurrentInstance();
|
||||
function exportExcel() {
|
||||
let xlsxParam = { raw: true };
|
||||
let wb = XLSX.utils.table_to_book(
|
||||
document.querySelector("#" + props.myId),
|
||||
xlsxParam
|
||||
);
|
||||
let wbout = XLSX.write(wb, {
|
||||
bookType: "xlsx",
|
||||
bookSST: true,
|
||||
type: "array"
|
||||
});
|
||||
closed();
|
||||
try {
|
||||
FileSaver.saveAs(
|
||||
new Blob([wbout], { type: "application/octet-stream" }),
|
||||
`${props.title}.xlsx`
|
||||
);
|
||||
} catch (e) {
|
||||
if (typeof console !== "undefined") console.log(e, wbout);
|
||||
}
|
||||
return wbout;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
80
src/components/MyComponents/Email/index.vue
Normal file
80
src/components/MyComponents/Email/index.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="form-item-box zj-email-wrap" :style="{ width: width }">
|
||||
<el-autocomplete v-model="email" v-bind="$attrs" :placeholder="placeholder" :fetch-suggestions="querySearch"
|
||||
:trigger-on-focus="false" class="inline-input" @select="handleSelect" @input="onInput" />
|
||||
<!-- <el-icon class="errorIcon">
|
||||
<circle-close-filled />
|
||||
</el-icon>
|
||||
<el-icon class="checkIcon">
|
||||
<circle-check-filled />
|
||||
</el-icon> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from '@/constant';
|
||||
import { ref, defineProps, defineEmits, defineExpose, onMounted } from "vue";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请填写邮箱",
|
||||
type: String
|
||||
},
|
||||
email: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:email"]);
|
||||
const onInput = (e) => {
|
||||
emits("update:email", e);
|
||||
};
|
||||
const restaurants = ref([]);
|
||||
const createFilter = (queryString) => {
|
||||
return (item) => {
|
||||
return item.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0;
|
||||
};
|
||||
};
|
||||
const querySearch = (queryString, callback) => {
|
||||
let results = JSON.parse(JSON.stringify(restaurants.value)); //把数组的浅复制换成深复制
|
||||
if (queryString.indexOf("@") > -1) {
|
||||
results.length = 0;
|
||||
callback(results);
|
||||
return false;
|
||||
}
|
||||
for (let item in results) {
|
||||
results[item].value = queryString + "" + restaurants.value[item].value;
|
||||
}
|
||||
callback(results);
|
||||
};
|
||||
|
||||
const loadAll = () => {
|
||||
return [
|
||||
{ value: "@qq.com" },
|
||||
{ value: "@mosty.com" },
|
||||
{ value: "@163.com" },
|
||||
{ value: "@outlook.com" },
|
||||
{ value: "@sohu.com" }
|
||||
];
|
||||
};
|
||||
const handleSelect = (item) => {
|
||||
emits("update:email", item.value);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
restaurants.value = loadAll();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.zj-email-wrap {
|
||||
::v-deep .el-autocomplete {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
247
src/components/MyComponents/FileUpload/index.vue
Normal file
247
src/components/MyComponents/FileUpload/index.vue
Normal file
@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<div class="main-box">
|
||||
<div class="file_box" v-for="(item, index) in fileList" :key="index">
|
||||
<div class="show_file" :style="{ width: width, height: width }">
|
||||
<div class="icon_box_y" :style="{ width: width, height: width }">
|
||||
<svg-icon :icon="getSuffix(item.url)" />
|
||||
<span class="file_name_box">{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="load_and_del" :style="{ width: width, height: width }">
|
||||
<el-icon class="load_and_del_icon" :size="18" color="#aaaaaa">
|
||||
<DeleteFilled v-if="props.isEdit" @click="delFile(index)" />
|
||||
</el-icon>
|
||||
<el-icon class="load_and_del_icon" :size="18" color="#aaaaaa">
|
||||
<Download @click="downloadFile(item.url)" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="file_box" v-if="fileList.length != props.limit && props.isEdit">
|
||||
<div class="upload_img" :style="{ width: width, height: width }">
|
||||
<div class="icon_box" :style="{ width: width, height: width }">
|
||||
<el-icon :size="30" color="#aaaaaa">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="file_box_item" :style="{ width: width, height: width }">
|
||||
<input
|
||||
type="file"
|
||||
:style="{ width: width, height: width }"
|
||||
class="file_input"
|
||||
id="file"
|
||||
@change="fileChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
defineExpose,
|
||||
computed,
|
||||
onMounted
|
||||
} from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import request from "@/utils/request";
|
||||
import axios from "axios";
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: "150px"
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
const fileList = ref([]);
|
||||
const count = ref(0); // 上传的数量
|
||||
|
||||
const emits = defineEmits(["update:modelValue", "handleChange"]);
|
||||
//获取后缀
|
||||
const getSuffix = (fileName) => {
|
||||
let suffix = "";
|
||||
try {
|
||||
suffix = fileName.substr(fileName.lastIndexOf(".") + 1, 4);
|
||||
if (suffix.indexOf("?") !== -1) suffix = suffix.replaceAll("?", "");
|
||||
} catch (err) {
|
||||
suffix = "";
|
||||
return "OTHER";
|
||||
}
|
||||
// fileName无后缀返回 false
|
||||
if (!suffix) return "";
|
||||
// 图片格式
|
||||
var imglist = ["png", "jpg", "jpeg", "bmp", "gif"];
|
||||
if (imglist.includes(suffix)) return "IMG";
|
||||
//txt
|
||||
if (suffix === "txt") return "TXT";
|
||||
//excel XLS
|
||||
const excelist = ["xls", "xlsx"];
|
||||
if (excelist.includes(suffix)) return "XLS";
|
||||
// 匹配 word
|
||||
var wordlist = ["doc", "docx"];
|
||||
if (wordlist.includes(suffix)) return "DOC";
|
||||
//pdf
|
||||
if (suffix === "pdf") return "PDF";
|
||||
//视频 音频
|
||||
var videolist = [
|
||||
"mp4",
|
||||
"m2v",
|
||||
"mkv",
|
||||
"rmvb",
|
||||
"wmv",
|
||||
"avi",
|
||||
"flv",
|
||||
"mov",
|
||||
"m4v"
|
||||
];
|
||||
if (videolist.includes(suffix)) return "VIDEO";
|
||||
var musiclist = ["mp3", "wav", "wmv"];
|
||||
if (musiclist.includes(suffix)) return "MUSIC";
|
||||
var pptlist = ["ppt", "pptx"];
|
||||
if (pptlist.includes(suffix)) return "PPT";
|
||||
//压缩包
|
||||
var yslist = ["7z", "rar", "zip", "apz", "ar", "hpk", "hyp", "hbc2"];
|
||||
if (yslist.includes(suffix)) return "YS";
|
||||
//否则返回other
|
||||
return "OTHER";
|
||||
};
|
||||
// 删除
|
||||
function delFile(index) {
|
||||
fileList.value = fileList.value.filter((item, i) => {
|
||||
return i !== index;
|
||||
});
|
||||
}
|
||||
// 文件下载
|
||||
function downloadFile(url) {
|
||||
window.open('/mosty-api/mosty-base/minio/image/download/'+url, "_blank");
|
||||
}
|
||||
// 选择文件
|
||||
function fileChange(e) {
|
||||
let file = document.getElementById("file").files[0];
|
||||
let name = file.name;
|
||||
let formData = new FormData();
|
||||
formData.append("file", file);
|
||||
axios
|
||||
.post("/mosty-api/mosty-base/minio/image/upload/id", formData, {
|
||||
"Content-type": "multipart/form-data"
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.status == 200 && res.data && res.data.code === 10000) {
|
||||
let url = res.data.data;
|
||||
let f = {
|
||||
url: url,
|
||||
name: name
|
||||
};
|
||||
fileList.value.push(f);
|
||||
count.value = count.value + 1;
|
||||
let list = fileList.value.map((item) => {
|
||||
return item.url;
|
||||
});
|
||||
emits("handleChange", JSON.stringify(list));
|
||||
} else {
|
||||
ElMessage.warning("文件上传失败");
|
||||
}
|
||||
});
|
||||
}
|
||||
onMounted(() => {
|
||||
if (props.modelValue) {
|
||||
let list = JSON.parse(props.modelValue);
|
||||
list.forEach((item, index) => {
|
||||
let temp = {
|
||||
url: item,
|
||||
name: "文件" + (index + 1)
|
||||
};
|
||||
fileList.value.push(temp);
|
||||
});
|
||||
count.value = list.length;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.main-box {
|
||||
width: 100%;
|
||||
.file_box {
|
||||
background-color: #112b63;
|
||||
border: 1px dashed #4579b5;
|
||||
margin: 10px 0 0 10px;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
.show_file {
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
&:hover > .load_and_del {
|
||||
display: block;
|
||||
}
|
||||
.load_and_del {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
.load_and_del_icon {
|
||||
cursor: pointer;
|
||||
margin-left:5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
.icon_box_y {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
.file_name_box {
|
||||
margin-top: 10px;
|
||||
width: 80%;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
::v-deep .svg-icon {
|
||||
font-size: 48px;
|
||||
}
|
||||
}
|
||||
.upload_img {
|
||||
position: relative;
|
||||
.icon_box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.file_box_item {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
left: 0;
|
||||
.file_input {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.file_box_item_show {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
198
src/components/MyComponents/FrameWork/index.vue
Normal file
198
src/components/MyComponents/FrameWork/index.vue
Normal file
@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<div class="form-item-box zk-frameWork-wrap" :style="{ width: width }">
|
||||
<el-select
|
||||
:model-value="frameWork"
|
||||
:placeholder="placeholder"
|
||||
@clear="handleClear"
|
||||
@change="selectChange"
|
||||
:clearable="clearable"
|
||||
v-bind="$attrs"
|
||||
:multiple="multiple"
|
||||
popper-class="frameWork-select"
|
||||
>
|
||||
<el-option value="1" style="display: none"></el-option>
|
||||
<el-input
|
||||
v-if="filterable"
|
||||
v-model="filterText"
|
||||
style="width: 96% !important; margin: 0 2%; font-size: 12px"
|
||||
:prefix-icon="Search"
|
||||
/>
|
||||
<div class="alllist">
|
||||
<el-tree
|
||||
ref="tree"
|
||||
:data="treeData"
|
||||
:props="defaultConf"
|
||||
default-expand-all
|
||||
:filter-node-method="filterNode"
|
||||
:show-checkbox="multiple"
|
||||
:node-key="nodeKey"
|
||||
@check-change="handleCheckChange"
|
||||
@node-click="clickNode"
|
||||
/>
|
||||
</div>
|
||||
</el-select>
|
||||
<!-- <el-icon class="errorIcon"><circle-close-filled /></el-icon>
|
||||
<el-icon class="checkIcon"><circle-check-filled /></el-icon> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from '@/constant';
|
||||
import { nextTick, ref, watch } from "vue";
|
||||
import { Search } from "@element-plus/icons-vue";
|
||||
const emits = defineEmits(["handleChange"]); //子组件向父组件事件传递
|
||||
const props = defineProps({
|
||||
clearable: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
multiple: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
filterable: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
treeData: {
|
||||
default: () => [],
|
||||
type: Array
|
||||
},
|
||||
placeholder: {
|
||||
default: "选择组织机构",
|
||||
type: String
|
||||
},
|
||||
defaultConf: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
children: "children",
|
||||
label: "label"
|
||||
})
|
||||
},
|
||||
frameWork: {
|
||||
type: [String, Array],
|
||||
default: ""
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
const nodeKey = "id";
|
||||
const filterText = ref("");
|
||||
const mineStatusValue = ref([]); //选中状态存贮
|
||||
nextTick(() => {
|
||||
if (props.frameWork) {
|
||||
if (typeof props.frameWork === "string") {
|
||||
//传过来的默认值类型
|
||||
if (props.frameWork) {
|
||||
tree.value.setCheckedKeys([props.frameWork], false);
|
||||
}
|
||||
} else {
|
||||
if (props.frameWork.length > 0) {
|
||||
tree.value.setCheckedKeys(props.frameWork, false);
|
||||
}
|
||||
}
|
||||
mineStatusValue.value = treeValueFind(props.treeData, props.frameWork);
|
||||
}
|
||||
});
|
||||
const tree = ref(null);
|
||||
let deferTimer;
|
||||
watch(filterText, (val) => {
|
||||
tree.value.filter(val);
|
||||
});
|
||||
const filterNode = (value, data) => {
|
||||
if (!value) return true;
|
||||
return data[props.defaultConf.label].indexOf(value) !== -1;
|
||||
};
|
||||
|
||||
//多选选中
|
||||
const handleCheckChange = () => {
|
||||
const res = tree.value.getCheckedNodes(true, true); // 这里两个true,1. 是否只是叶子节点 2. 是否包含半选节点
|
||||
mineStatusValue.value = res;
|
||||
clearTimeout(deferTimer);
|
||||
deferTimer = setTimeout(() => {
|
||||
emits("handleChange", res);
|
||||
}, 200);
|
||||
};
|
||||
//节点选择
|
||||
const clickNode = (data, node, obj) => {
|
||||
if (props.multiple) {
|
||||
// 多选不执行
|
||||
const index = mineStatusValue.value.findIndex((d) => d.id === data.id);
|
||||
if (index > -1) {
|
||||
tree.value.setChecked(data, false);
|
||||
} else {
|
||||
tree.value.setChecked(data, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!data.children) {
|
||||
mineStatusValue.value.push(data.id);
|
||||
tree.value.setCheckedKeys([data.id], false);
|
||||
}
|
||||
};
|
||||
//select值变化
|
||||
const selectChange = (e) => {
|
||||
if (!props.multiple || !props.treeData.length) {
|
||||
return false;
|
||||
}
|
||||
const arrNew = [];
|
||||
const dataLength = mineStatusValue.value.length;
|
||||
const eleng = e.length;
|
||||
for (let i = 0; i < dataLength; i++) {
|
||||
for (let j = 0; j < eleng; j++) {
|
||||
if (e[j] === mineStatusValue.value[i][props.defaultConf.label]) {
|
||||
arrNew.push(mineStatusValue.value[i][nodeKey]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
tree.value.setCheckedKeys(arrNew, false);
|
||||
}, 200);
|
||||
};
|
||||
//select clear
|
||||
const handleClear = (e) => {
|
||||
mineStatusValue.value = [];
|
||||
tree.value.setCheckedKeys([], false);
|
||||
};
|
||||
const treeValueFind = (tree, arr, newArr = []) => {
|
||||
if (typeof arr === "string") {
|
||||
tree.forEach((el) => {
|
||||
if (el[nodeKey] === arr) {
|
||||
newArr.push(el);
|
||||
}
|
||||
if (el[props.defaultConf.children]) {
|
||||
treeValueFind(el[props.defaultConf.children], arr, newArr);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (let i = arr.length; i >= 0; i--) {
|
||||
tree.forEach((el) => {
|
||||
if (el[nodeKey] === arr[i]) {
|
||||
newArr.push(el);
|
||||
arr.splice(i, 1);
|
||||
}
|
||||
if (el[props.defaultConf.children] && arr.length > 0) {
|
||||
treeValueFind(el[props.defaultConf.children], arr, newArr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return newArr;
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.optionclass {
|
||||
height: auto;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow-y: overflow;
|
||||
}
|
||||
.zk-frameWork-wrap {
|
||||
.el-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
83
src/components/MyComponents/FrameWork2/index.vue
Normal file
83
src/components/MyComponents/FrameWork2/index.vue
Normal file
@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="form-item-box" :style="{ width: width }">
|
||||
<el-cascader
|
||||
class="el-cascader-zj"
|
||||
:placeholder="placeholder"
|
||||
:options="tableData"
|
||||
v-bind="$attrs"
|
||||
v-model="modelValue"
|
||||
@change="handleChange"
|
||||
:props="endProps"
|
||||
:filterable="filterable"
|
||||
/>
|
||||
<!-- <el-icon class="errorIcon"><circle-close-filled /></el-icon>
|
||||
<el-icon class="checkIcon"><circle-check-filled /></el-icon> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from '@/constant';
|
||||
import { ref, defineProps, defineEmits, defineExpose,computed } from "vue";
|
||||
import { getSystemMeny } from "@/api/user-manage";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请选择",
|
||||
type: String
|
||||
},
|
||||
multiple: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
filterable: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
modelValue: {
|
||||
default: [],
|
||||
type: Array
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
const endProps = computed(() => {
|
||||
let re = { children: 'sysMenuList', value: 'id', label: 'menuName' }
|
||||
if (props.multiple === true) {
|
||||
re.multiple = true;
|
||||
}
|
||||
return re;
|
||||
})
|
||||
const tableData = ref([]);
|
||||
const getSysMenuTree = async () => {
|
||||
const params = {
|
||||
menuName: "",
|
||||
current: 1,
|
||||
size: 999
|
||||
}
|
||||
const res = await getSystemMeny(params);
|
||||
tableData.value = res?.records;
|
||||
};
|
||||
getSysMenuTree();
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const handleChange = (e) => {
|
||||
if (props.multiple === true) {
|
||||
const data = e.map((item) => {
|
||||
return item[item.length - 1];
|
||||
});
|
||||
emits("update:modelValue", data);
|
||||
} else {
|
||||
const data = e ? e[e.length - 1] : ''
|
||||
emits("update:modelValue", data);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-cascader-zj{
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
</style>
|
38
src/components/MyComponents/IdentityCard/index.vue
Normal file
38
src/components/MyComponents/IdentityCard/index.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div
|
||||
class="form-item-box"
|
||||
:style="{ width: width}"
|
||||
>
|
||||
<el-input
|
||||
:placeholder="placeholder"
|
||||
v-bind="$attrs"
|
||||
v-model="modelValue"
|
||||
@input="onInput"
|
||||
></el-input>
|
||||
<!-- <el-icon class="errorIcon"><circle-close-filled /></el-icon>
|
||||
<el-icon class="checkIcon"><circle-check-filled /></el-icon> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from '@/constant';
|
||||
import { defineProps, defineEmits } from "vue";
|
||||
const props = defineProps({
|
||||
placeholder: {
|
||||
default: "请输入身份证号",
|
||||
type: String
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const onInput = (e) => {
|
||||
emits("update:modelValue", e);
|
||||
};
|
||||
</script>
|
71
src/components/MyComponents/MarkdownEdit/index.vue
Normal file
71
src/components/MyComponents/MarkdownEdit/index.vue
Normal file
@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div class="markdown-wrap">
|
||||
<!---->
|
||||
<div id="markdown-box">
|
||||
<strong v-html="modelValue"></strong>
|
||||
</div>
|
||||
<div style="margin-top: 1vw">
|
||||
<el-button type="primary" @click="saveEdit">确定详情信息</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import MKEditor from "@toast-ui/editor";
|
||||
import "@toast-ui/editor/dist/toastui-editor.css";
|
||||
import "@toast-ui/editor/dist/i18n/zh-cn.js";
|
||||
|
||||
import { COMPONENT_WIDTH } from "@/constant";
|
||||
import {
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
defineExpose,
|
||||
onMounted,
|
||||
watch
|
||||
} from "vue";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请填写手机号",
|
||||
type: String
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: "800px",
|
||||
type: String
|
||||
}
|
||||
});
|
||||
let mkEditor;
|
||||
let el;
|
||||
onMounted(() => {
|
||||
el = document.querySelector("#markdown-box");
|
||||
initEditor();
|
||||
});
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const initEditor = () => {
|
||||
mkEditor = new MKEditor({
|
||||
el,
|
||||
height: "700px",
|
||||
previewStyle: "vertical",
|
||||
language: "zh-CN",
|
||||
initiaValue:props.modelValue
|
||||
});
|
||||
mkEditor.getMarkdown();
|
||||
};
|
||||
const saveEdit = () => {
|
||||
emits("update:modelValue", mkEditor.getHTML());
|
||||
};
|
||||
const onInput = (e) => {
|
||||
emits("update:modelValue", e);
|
||||
};
|
||||
//回显
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.markdown-wrap {
|
||||
}
|
||||
</style>
|
31
src/components/MyComponents/Other/index.vue
Normal file
31
src/components/MyComponents/Other/index.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="form-item-box" :style="{ width: width }">
|
||||
<el-input :placeholder="placeholder" v-bind="$attrs" v-model="modelValue" @input="onInput" ></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from "@/constant";
|
||||
import { ref, defineProps, defineEmits, defineExpose } from "vue";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请填写手机号",
|
||||
type: String
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const onInput = (e) => {
|
||||
emits("update:modelValue", e);
|
||||
};
|
||||
</script>
|
||||
|
32
src/components/MyComponents/Phone/index.vue
Normal file
32
src/components/MyComponents/Phone/index.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="form-item-box" :style="{ width: width }">
|
||||
<el-input :placeholder="placeholder" v-bind="$attrs" v-model="modelValue" @input="onInput" ></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from '@/constant';
|
||||
import { ref, defineProps, defineEmits, defineExpose } from "vue";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请填写手机号",
|
||||
type: String
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const onInput = (e) => {
|
||||
emits("update:modelValue", e);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
109
src/components/MyComponents/Provinces/index.vue
Normal file
109
src/components/MyComponents/Provinces/index.vue
Normal file
@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div class="form-item-box">
|
||||
<el-select v-model="province" clearable placeholder="请选择省份">
|
||||
<el-option v-for="item in areas" :value="item.code" :label="item.name" :key="item.code">{{ item.name }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-select clearable :disabled="!province" style="margin: 0 10px" v-model="city" placeholder="请选择城市">
|
||||
<el-option v-for="item in selectCity" :value="item.code" :label="item.name" :key="item.code">{{ item.name }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-select clearable :disabled="!province || !city" v-model="area" placeholder="请选择区域">
|
||||
<el-option v-for="item in selectArea" :value="item.code" :label="item.name" :key="item.code">{{ item.name }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import allAreas from "@/constant/pca-code.json";
|
||||
import {
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
defineExpose,
|
||||
computed,
|
||||
watch
|
||||
} from "vue";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请选择省市区",
|
||||
type: String
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
}
|
||||
});
|
||||
|
||||
let province = ref("");
|
||||
let city = ref("");
|
||||
let area = ref("");
|
||||
let areas = ref(allAreas);
|
||||
|
||||
let selectCity = ref([]);
|
||||
let selectArea = ref([]);
|
||||
//分发事件给父组件
|
||||
//分发事件给父组件
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
//监听省份变化
|
||||
watch(
|
||||
() => province.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
let cities = areas.value.find(
|
||||
(item) => item.code === province.value
|
||||
)?.children;
|
||||
selectCity.value = cities;
|
||||
}
|
||||
city.value = "";
|
||||
area.value = "";
|
||||
}
|
||||
);
|
||||
|
||||
//监听城市变化
|
||||
watch(
|
||||
() => city.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
let area = selectCity.value.find(
|
||||
(item) => item.code === city.value
|
||||
)?.children;
|
||||
selectArea.value = area;
|
||||
}
|
||||
area.value = "";
|
||||
}
|
||||
);
|
||||
|
||||
//监听区域变化
|
||||
watch(
|
||||
() => area.value,
|
||||
(val) => {
|
||||
let provinceData = {
|
||||
code: province.value,
|
||||
name:
|
||||
province.value &&
|
||||
allAreas.find((item) => item.code === province.value).name
|
||||
};
|
||||
let cityData = {
|
||||
code: city.value,
|
||||
name:
|
||||
city.value &&
|
||||
selectCity.value &&
|
||||
selectCity.value.find((item) => item.code === city.value).name
|
||||
};
|
||||
let areaData = {
|
||||
code: val,
|
||||
name:
|
||||
val &&
|
||||
selectArea.value &&
|
||||
selectArea.value.find((item) => item.code === val).name
|
||||
};
|
||||
emits("update:modelValue", `${provinceData},${cityData},${areaData}`);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
62
src/components/MyComponents/Provinces2/index.vue
Normal file
62
src/components/MyComponents/Provinces2/index.vue
Normal file
@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div class="form-item-box" :style="{ width: width }">
|
||||
<el-cascader class="el-cascader-zj" :props="{ value: 'label', label: 'label', children: 'children' }"
|
||||
:options="arercity" expand-trigger="hover" change-on-select @change="onInChange" :placeholder="placeholder"
|
||||
v-bind="$attrs" v-model="value"></el-cascader>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from '@/constant';
|
||||
import allAreas from "./provicesData";
|
||||
import {
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
defineExpose,
|
||||
computed,
|
||||
nextTick,
|
||||
watch
|
||||
} from "vue";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请选择地区位置",
|
||||
type: String
|
||||
},
|
||||
|
||||
provinces2: {
|
||||
default: () => [],
|
||||
type: Array
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
const value = ref([]);
|
||||
|
||||
nextTick(() => {
|
||||
if (props.provinces2.length > 0) {
|
||||
init(props.provinces2);
|
||||
}
|
||||
});
|
||||
|
||||
const init = (data) => { };
|
||||
const registerAddress = ref([]);
|
||||
|
||||
const arercity = ref(allAreas);
|
||||
const emits = defineEmits(["update:provinces2"]);
|
||||
const onInChange = (e) => {
|
||||
emits("update:provinces2", e);
|
||||
};
|
||||
// const onInput = (e) => {
|
||||
// emits("update:provinces2", e);
|
||||
// };
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-cascader-zj {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
6138
src/components/MyComponents/Provinces2/provicesData.js
Normal file
6138
src/components/MyComponents/Provinces2/provicesData.js
Normal file
File diff suppressed because it is too large
Load Diff
288
src/components/MyComponents/RichOnly/index.vue
Normal file
288
src/components/MyComponents/RichOnly/index.vue
Normal file
@ -0,0 +1,288 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
:title="titleValue"
|
||||
width="1400px"
|
||||
:model-value="modelValue"
|
||||
@close="closed"
|
||||
>
|
||||
<el-form :model="listQuery" :inline="true">
|
||||
<el-form-item label="所属部门">
|
||||
<MOSTY.Department width="100%" clearable v-model="listQuery.ssbmdm" />
|
||||
</el-form-item>
|
||||
<el-form-item label="圈层名称">
|
||||
<el-input
|
||||
v-model="listQuery.qcmc"
|
||||
placeholder="请输入圈层名称"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="success" @click="handleFilter">查询</el-button>
|
||||
<el-button type="info" @click="reset()"> 重置 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="tabBox" style="margin-top: 0px" v-if="modelValue">
|
||||
<el-table
|
||||
ref="multipleUserRef"
|
||||
@selection-change="handleSelectionChange"
|
||||
:data="tableData"
|
||||
border
|
||||
style="width: 100%"
|
||||
:row-key="keyid"
|
||||
height="450"
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55"
|
||||
:reserve-selection="true"
|
||||
v-if="props.multiple"
|
||||
/>
|
||||
<el-table-column width="55" #default="{ row }" v-else>
|
||||
<el-radio v-model="ridioIndex" :label="row.id"></el-radio>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="序号"
|
||||
type="index"
|
||||
align="center"
|
||||
sortable
|
||||
width="80"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="ssbm"
|
||||
label="所属部门"
|
||||
show-overflow-tooltip
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="qcmc"
|
||||
show-overflow-tooltip
|
||||
label="圈层名称"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="qclx"
|
||||
show-overflow-tooltip
|
||||
label="圈层类型"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<dict-tag :options="D_BZ_QCLX" :value="row.qclx" :tag="false" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="qcjb"
|
||||
show-overflow-tooltip
|
||||
label="圈层等级"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<dict-tag :options="D_BZ_QCDJ" :value="row.qcjb" :tag="false" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="fenye" :style="{ top: tableHeight + 'px' }">
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="listQuery.pageCurrent"
|
||||
:page-sizes="[2, 5, 10, 20]"
|
||||
:page-size="listQuery.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
></el-pagination>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="closed">取消</el-button>
|
||||
<el-button type="primary" @click="onComfirm">确认</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as rule from "@/utils/rules.js";
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
|
||||
import {
|
||||
defineProps,
|
||||
watch,
|
||||
ref,
|
||||
onMounted,
|
||||
nextTick,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_BZ_QCLX, D_BZ_QCDJ } = proxy.$dict("D_BZ_QCLX", "D_BZ_QCDJ");
|
||||
const props = defineProps({
|
||||
//是否显示
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
//标题
|
||||
titleValue: {
|
||||
type: String,
|
||||
default: "选择圈层"
|
||||
},
|
||||
//是否多选
|
||||
multiple: {
|
||||
default: true,
|
||||
type: Boolean
|
||||
},
|
||||
//已经选中得数据回显
|
||||
data: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
});
|
||||
const keyid = (row) => {
|
||||
return row.id;
|
||||
};
|
||||
const total = ref(0);
|
||||
const ridioIndex = ref(null);
|
||||
const listQuery = ref({
|
||||
pageCurrent: 1,
|
||||
pageSize: 20,
|
||||
qcmc: "",
|
||||
ssbmdm: ""
|
||||
});
|
||||
const form = ref({});
|
||||
const tableData = ref([]);
|
||||
const emits = defineEmits(["close", "choosedQc"]);
|
||||
const closed = () => {
|
||||
emits("close", false);
|
||||
};
|
||||
const reset = () => {
|
||||
listQuery.value = {
|
||||
pageCurrent: 1,
|
||||
pageSize: 20,
|
||||
qcmc: "",
|
||||
ssbmdm: ""
|
||||
};
|
||||
getListData();
|
||||
};
|
||||
//确认选中
|
||||
const onComfirm = () => {
|
||||
if (props.multiple) {
|
||||
//多选
|
||||
const List = JSON.parse(JSON.stringify(multipleSelectionUser.value));
|
||||
if (List.length === 0) {
|
||||
proxy.$message.warning("请选择圈层");
|
||||
return;
|
||||
}
|
||||
emits("choosedQc", List);
|
||||
} else {
|
||||
//单选
|
||||
if (![ridioIndex.value][0]) {
|
||||
proxy.$message.warning("请选择圈层");
|
||||
return;
|
||||
}
|
||||
const info = tableData.value.find((item) => {
|
||||
return item.id === ridioIndex.value;
|
||||
});
|
||||
emits("choosedQc", [info]);
|
||||
}
|
||||
closed();
|
||||
};
|
||||
onMounted(() => {
|
||||
getListData();
|
||||
});
|
||||
/**
|
||||
* pageSize 改变触发
|
||||
*/
|
||||
const handleSizeChange = (currentSize) => {
|
||||
listQuery.value.pageSize = currentSize;
|
||||
getListData();
|
||||
};
|
||||
|
||||
/**
|
||||
* 页码改变触发
|
||||
*/
|
||||
const handleCurrentChange = (currentPage) => {
|
||||
listQuery.value.pageSize = currentPage;
|
||||
getListData();
|
||||
};
|
||||
//圈层数据
|
||||
const getListData = async () => {
|
||||
qcckGet(listQuery.value, "/mosty-jcgl/qc/selectQcList").then((res) => {
|
||||
tableData.value = res?.records;
|
||||
multipleUser(props.data, tableData.value);
|
||||
total.value = Number(res.total);
|
||||
});
|
||||
};
|
||||
const handleFilter = () => {
|
||||
listQuery.value.pageCurrent = 1;
|
||||
getListData();
|
||||
};
|
||||
|
||||
const multipleUserRef = ref(null); //表单
|
||||
//多选选中的数据
|
||||
const multipleSelectionUser = ref([]);
|
||||
const handleSelectionChange = (val) => {
|
||||
multipleSelectionUser.value = val;
|
||||
};
|
||||
//回显
|
||||
function multipleUser(row, list) {
|
||||
if (row) {
|
||||
if (props.multiple) {
|
||||
row.forEach((item) => {
|
||||
list.forEach((select) => {
|
||||
if (item.id == select.id) {
|
||||
if (multipleUserRef.value) {
|
||||
multipleUserRef.value.toggleRowSelection(select, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (val === true) {
|
||||
handleFilter();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
if (multipleUserRef.value) multipleUser(val, tableData.value);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/css/layout.scss";
|
||||
@import "@/assets/css/element-plus.scss";
|
||||
::v-deep .el-form--inline {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
::v-deep .el-radio__label {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" >
|
||||
.el-dialog {
|
||||
--el-dialog-bg-color: #001238 !important;
|
||||
}
|
||||
.el-dialog__title {
|
||||
color: #fff !important;
|
||||
}
|
||||
</style>
|
||||
|
49
src/components/MyComponents/Select/index.vue
Normal file
49
src/components/MyComponents/Select/index.vue
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
<template>
|
||||
<div class="Select-wrap" :style="{ width: width }">
|
||||
<el-select :disabled="props.disabled" v-bind="$attrs" v-model="modelValue" @change="hanlderSelect" :popper-class="selectOption.length > 20 ? 'nation-select' : ''" :placeholder="placeholder">
|
||||
<el-option v-for="item in dictEnum" :key="item.value" :label="item.zdmc || item.label" :value="item.dm || item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { nextTick, onBeforeMount, ref } from "vue";
|
||||
const emits = defineEmits(["change"]); //子组件向父组件事件传递
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请选择",
|
||||
type: String
|
||||
},
|
||||
disabled:{
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
dictEnum: {
|
||||
default: Array,
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: '100%',
|
||||
type: String
|
||||
}
|
||||
});
|
||||
const selectOption = ref([]);
|
||||
|
||||
const hanlderSelect = (data) => {
|
||||
emits("change", data);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.Select-wrap {
|
||||
::v-deep .el-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
52
src/components/MyComponents/Sex/index.vue
Normal file
52
src/components/MyComponents/Sex/index.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="form-item-box" :style="{ width: width }">
|
||||
<el-select :disabled="disabled" v-model="sex" placeholder="请选择性别" @change="onChange">
|
||||
<el-option
|
||||
v-for="item in D_BZ_XB"
|
||||
:key="item"
|
||||
:label="item.zdmc"
|
||||
:value="item.dm"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from "@/constant";
|
||||
import {
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
defineExpose,
|
||||
getCurrentInstance,
|
||||
onBeforeMount
|
||||
} from "vue";
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { D_BZ_XB } = proxy.$dict("D_BZ_XB");
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
sex: {
|
||||
type: String
|
||||
},
|
||||
disabled:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
|
||||
const emits = defineEmits(["update:sex"]);
|
||||
const onChange = (e) => {
|
||||
emits("update:sex", e);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.manIcon,
|
||||
.womanIcon {
|
||||
font-size: 30px;
|
||||
}
|
||||
</style>
|
49
src/components/MyComponents/StationSelect/index.vue
Normal file
49
src/components/MyComponents/StationSelect/index.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div class="form-item-box zj-packageSelect-wrap" :style="{ width: width }">
|
||||
<el-select v-bind="$attrs" :model-value="modelValue" @change="hanlderSelect" :popper-class="selectOption.length > 20 ? 'nation-select' : ''">
|
||||
<el-option v-for="item in selectOption" :key="item.id" :label="item.postName" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from '@/constant';
|
||||
import { onBeforeMount, ref } from "vue";
|
||||
import { selectJobPage } from "@/api/user-manage";
|
||||
const emits = defineEmits(["handleChange"]); //子组件向父组件事件传递
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
placeholder: {
|
||||
default: "请选择",
|
||||
type: String
|
||||
},
|
||||
modelValue: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
dictEnum: {
|
||||
default: "",
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
const selectOption = ref([]);
|
||||
onBeforeMount(async () => {
|
||||
const res = await selectJobPage({ page: 1, size: 9999 });
|
||||
selectOption.value = [...res.records];
|
||||
});
|
||||
const hanlderSelect = (data) => {
|
||||
emits("handleChange", data);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.zj-packageSelect-wrap {
|
||||
::v-deep .el-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
299
src/components/MyComponents/Upload/index.vue
Normal file
299
src/components/MyComponents/Upload/index.vue
Normal file
@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<div class="form-item-box" :style="{ width: width }">
|
||||
<el-upload
|
||||
v-bind="$attrs"
|
||||
:headers="headers"
|
||||
:multiple="false"
|
||||
class="avatar-uploader"
|
||||
:limit="props.limit"
|
||||
:action="actionUrl"
|
||||
list-type="picture-card"
|
||||
:file-list="fileList"
|
||||
show-file-list
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="handlerSuccess"
|
||||
:before-upload="beforeImgUpload"
|
||||
>
|
||||
<template #default>
|
||||
<el-icon> <Plus /> </el-icon>
|
||||
</template>
|
||||
<template #file="{ file }">
|
||||
<div v-if="props.isImg">
|
||||
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
|
||||
<el-icon>
|
||||
<zoom-in />
|
||||
</el-icon>
|
||||
</span>
|
||||
<span
|
||||
v-if="!disabled"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file, fileList)"
|
||||
>
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="file-wrap">
|
||||
<span>
|
||||
<svg-icon :icon="getSuffix(file.name)" />
|
||||
</span>
|
||||
<span class="file-name">{{ file.name }}</span>
|
||||
</div>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
v-if="!disabled"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleDownload(file)"
|
||||
>
|
||||
<el-icon>
|
||||
<Download />
|
||||
</el-icon>
|
||||
</span>
|
||||
<span
|
||||
v-if="!disabled"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file, fileList)"
|
||||
>
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<el-dialog v-model="dialogVisible">
|
||||
<img style="width: 100%" :src="dialogImageUrl" alt="" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { COMPONENT_WIDTH } from "@/constant";
|
||||
import {
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
defineExpose,
|
||||
computed,
|
||||
watch,
|
||||
onMounted
|
||||
} from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import type from "element-plus/es/components/upload/src/upload.type";
|
||||
import { useStore } from "vuex";
|
||||
const props = defineProps({
|
||||
//获取组件传值
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
isImg: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
width: {
|
||||
default: COMPONENT_WIDTH,
|
||||
type: String
|
||||
}
|
||||
});
|
||||
|
||||
const actionUrl = computed(() =>
|
||||
props.isImg
|
||||
? "/mosty-api/mosty-base/minio/image/upload/id"
|
||||
: "/mosty-api/mosty-base/minio/file/upload"
|
||||
);
|
||||
|
||||
const emits = defineEmits(["update:modelValue", "handleChange"]);
|
||||
|
||||
//获取后缀
|
||||
const getSuffix = (fileName) => {
|
||||
let suffix = "";
|
||||
try {
|
||||
suffix = fileName.substr(fileName.lastIndexOf(".") + 1, 4); //截取最后一个点号后4个字符
|
||||
} catch (err) {
|
||||
suffix = "";
|
||||
return "OTHER";
|
||||
}
|
||||
// fileName无后缀返回 false
|
||||
if (!suffix) return "";
|
||||
|
||||
// 图片格式
|
||||
var imglist = ["png", "jpg", "jpeg", "bmp", "gif"];
|
||||
if (imglist.includes(suffix)) return "IMG";
|
||||
|
||||
//txt
|
||||
if (suffix === "txt") return "TXT";
|
||||
|
||||
//excel XLS
|
||||
const excelist = ["xls", "xlsx"];
|
||||
if (excelist.includes(suffix)) return "XLS";
|
||||
|
||||
// 匹配 word
|
||||
var wordlist = ["doc", "docx"];
|
||||
if (wordlist.includes(suffix)) return "DOC";
|
||||
|
||||
//pdf
|
||||
if (suffix === "pdf") return "PDF";
|
||||
|
||||
//视频 音频
|
||||
var videolist = [
|
||||
"mp4",
|
||||
"m2v",
|
||||
"mkv",
|
||||
"rmvb",
|
||||
"wmv",
|
||||
"avi",
|
||||
"flv",
|
||||
"mov",
|
||||
"m4v"
|
||||
];
|
||||
if (videolist.includes(suffix)) return "VIDEO";
|
||||
|
||||
var musiclist = ["mp3", "wav", "wmv"];
|
||||
if (musiclist.includes(suffix)) return "MUSIC";
|
||||
|
||||
var pptlist = ["ppt", "pptx"];
|
||||
if (pptlist.includes(suffix)) return "PPT";
|
||||
|
||||
//压缩包
|
||||
var yslist = ["7z", "rar", "zip", "apz", "ar", "hpk", "hyp", "hbc2"];
|
||||
if (yslist.includes(suffix)) return "YS";
|
||||
|
||||
//否则返回other
|
||||
return "OTHER";
|
||||
};
|
||||
|
||||
const imageUrl = ref("");
|
||||
const store = useStore();
|
||||
const dialogImageUrl = ref("");
|
||||
const dialogVisible = ref(false);
|
||||
const disabled = ref(false);
|
||||
const headers = ref({
|
||||
Authorization: store.getters.token
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (props.modelValue) {
|
||||
fileList.value = props.modelValue.map((el) => {
|
||||
return {
|
||||
url: `/mosty-api/mosty-base/minio/image/download/` + el
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
const fileList = ref([]);
|
||||
const handlerSuccess = (res, file) => {
|
||||
file.url = `/mosty-api/mosty-base/minio/image/download/` + res.data;
|
||||
fileList.value.push(file);
|
||||
props.modelValue.push(res.data);
|
||||
emits("handleChange", props.modelValue);
|
||||
// emits("update:modelValue", props.modelValue);
|
||||
};
|
||||
const handlePreview = (file) => {};
|
||||
const handleExceed = (files, fileList) => {
|
||||
ElMessage.warning(`限制,只能上传${props.limit}个文件或图片`);
|
||||
};
|
||||
|
||||
const beforeImgUpload = (file) => {
|
||||
if (props.isImg) {
|
||||
let isIMG = false;
|
||||
if (getSuffix(file.name) === "IMG") {
|
||||
isIMG = true;
|
||||
}
|
||||
const isLt5M = file.size / 1024 / 1024 < 5;
|
||||
if (!isIMG) {
|
||||
ElMessage.error("上传图片只能是jpg/png/jpeg/bmp/gif格式!");
|
||||
}
|
||||
if (!isLt5M) {
|
||||
ElMessage.error("上传图片大小不能超过 5MB!");
|
||||
}
|
||||
return isIMG && isLt5M;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
const handleAvatarSuccess = (res, file) => {
|
||||
imageUrl.value = URL.createObjectURL(file.raw);
|
||||
};
|
||||
//查询图片
|
||||
const handlePictureCardPreview = (file) => {
|
||||
dialogImageUrl.value = file.url;
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
const handleDownload = (file) => {
|
||||
window.open(file.response.data);
|
||||
};
|
||||
const handleRemove = (file) => {
|
||||
let index = fileList.value.findIndex(function (item) {
|
||||
return item.url === file.url;
|
||||
});
|
||||
fileList.value.splice(index, 1);
|
||||
props.modelValue.splice(index, 1);
|
||||
emits("handleChange", props.modelValue);
|
||||
// emits("update:modelValue", props.modelValue);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.el-icon.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.file-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
::v-deep .svg-icon {
|
||||
font-size: 48px;
|
||||
margin: 28px 0 2px 0;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
width: 88%;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
/*将对象作为弹性伸缩盒子模型显示*/
|
||||
display: -webkit-box;
|
||||
/*设置子元素排列方式*/
|
||||
-webkit-box-orient: vertical;
|
||||
/*设置显示的行数,多出的部分会显示为...*/
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
}
|
||||
</style>
|
40
src/components/MyComponents/index.js
Normal file
40
src/components/MyComponents/index.js
Normal file
@ -0,0 +1,40 @@
|
||||
import AddressSelect from "./AddressSelect/index.vue";
|
||||
import FrameWork from "./FrameWork/index.vue";
|
||||
import FrameWork2 from "./FrameWork2/index.vue";
|
||||
import Phone from "./Phone/index.vue";
|
||||
import IdentityCard from "./IdentityCard/index.vue";
|
||||
import Email from "./Email/index.vue";
|
||||
import Other from "./Other/index.vue";
|
||||
import Sex from "./Sex/index.vue";
|
||||
import Select from "./Select/index.vue";
|
||||
import Upload from "./Upload/index.vue";
|
||||
import Department from "./Department/index.vue";
|
||||
import DepartmentTree from "./DepartmentTree/index.vue";
|
||||
import ChooseIcon from "./ChooseIcon/index.vue";
|
||||
import StationSelect from "./StationSelect/index.vue";
|
||||
import Provinces from "./Provinces2/index.vue";
|
||||
import MarkdownEdit from "./MarkdownEdit/index.vue";
|
||||
import FileUpload from "./FileUpload/index.vue";
|
||||
import RichOnly from "./RichOnly/index.vue";
|
||||
import Date from "./Date/index.vue";
|
||||
export {
|
||||
AddressSelect,
|
||||
FrameWork,
|
||||
Phone,
|
||||
IdentityCard,
|
||||
Email,
|
||||
Other,
|
||||
Sex,
|
||||
Select,
|
||||
Upload,
|
||||
FrameWork2,
|
||||
Department,
|
||||
DepartmentTree,
|
||||
ChooseIcon,
|
||||
StationSelect,
|
||||
Provinces,
|
||||
MarkdownEdit,
|
||||
FileUpload,
|
||||
RichOnly,
|
||||
Date
|
||||
};
|
Reference in New Issue
Block a user