zhl-methods 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,105 @@
1
+ <template>
2
+ <TableView
3
+ :loading="state.loading"
4
+ :dataSource="state.dataSource"
5
+ :pagination="paginationConfig"
6
+ height="calc(100vh - 371px)"
7
+ >
8
+ <template v-for="(_, slot) in Slots" v-slot:[slot]="scope">
9
+ <slot :name="slot" v-bind="scope" />
10
+ </template>
11
+ </TableView>
12
+ </template>
13
+ <script setup lang="ts">
14
+ import { computed, onMounted, reactive, useSlots } from "vue";
15
+ const Slots = useSlots();
16
+ import TableView from "./index.vue";
17
+ const props = defineProps({
18
+ //Promise 请求方法
19
+ api: { type: Function, default: () => false },
20
+ //请求参数
21
+ apiParams: { type: Object, default: () => ({}) },
22
+ //是否开启分页
23
+ isPage: { type: Boolean, default: () => true },
24
+ //是否进入页面自动请求
25
+ autoRequest: { type: Boolean, default: () => true },
26
+ //设置自定义参数
27
+ checkParams: { type: Function },
28
+ //设置自定义返回值
29
+ checkReturnValue: { type: Function },
30
+ });
31
+
32
+ const state = reactive({
33
+ loading: false,
34
+ pagination: {
35
+ current: 1,
36
+ pageSize: 15,
37
+ total: 0,
38
+ },
39
+ dataSource: [],
40
+ });
41
+ const paginationConfig = computed(() => {
42
+ if (props.isPage) {
43
+ return {
44
+ ...state.pagination,
45
+ onChange: (page: number, limit: number) => pageChange(page, limit),
46
+ };
47
+ }
48
+ return false;
49
+ });
50
+ const pageChange = (page: number, limit: number) => {
51
+ state.pagination.current = page;
52
+ state.pagination.pageSize = limit;
53
+ getData();
54
+ };
55
+ const getData = async () => {
56
+ let params = { ...props.apiParams };
57
+
58
+ if (props.isPage) {
59
+ params = { ...props.apiParams, ...state.pagination };
60
+ }
61
+ if (props.checkParams) {
62
+ params = props.checkParams(params);
63
+ }
64
+ try {
65
+ state.loading = true;
66
+ let res = await props.api(params);
67
+ state.loading = false;
68
+ if (res.code == 200) {
69
+ let resData = res.data;
70
+ console.log(resData);
71
+ if (props.checkReturnValue) {
72
+ resData = props.checkReturnValue(res.data);
73
+ }
74
+ if (props.isPage) {
75
+ state.dataSource = resData.data;
76
+ state.pagination.total = resData.total;
77
+ } else {
78
+ state.dataSource = resData;
79
+ }
80
+ }
81
+ } catch (error) {
82
+ state.loading = false;
83
+ console.log(error);
84
+ }
85
+ };
86
+ const refresh = () => {
87
+ pageChange(1, 15);
88
+ };
89
+ const clearData = () => {
90
+ state.dataSource = [];
91
+ state.pagination.current = 1;
92
+ state.pagination.pageSize = 15;
93
+ state.pagination.total = 0;
94
+ };
95
+ onMounted(() => {
96
+ if (props.autoRequest && props.api) {
97
+ getData();
98
+ }
99
+ });
100
+ defineExpose({
101
+ refresh,
102
+ clearData,
103
+ dataSource: computed(() => state.dataSource),
104
+ });
105
+ </script>
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <a-table
3
+ :scroll="{
4
+ scrollToFirstRowOnChange: true,
5
+ y: tableHeight,
6
+ }"
7
+ :pagination="
8
+ props.pagination
9
+ ? {
10
+ ...pagination,
11
+ showTotal: (total: number) => `共 ${total} 条`,
12
+ pageSizeOptions: ['15', '30', '50', '100', '300', '500'],
13
+ }
14
+ : false
15
+ "
16
+ >
17
+ <template v-for="(_, slot) in Slots" v-slot:[slot]="scope">
18
+ <slot :name="slot" v-bind="scope" />
19
+ </template>
20
+ </a-table>
21
+ </template>
22
+ <script setup lang="ts">
23
+ import { computed, useSlots } from "vue";
24
+ const Slots = useSlots();
25
+ const props = defineProps({
26
+ //表格高度 只能为px vh calc()
27
+ height: {
28
+ type: String,
29
+ },
30
+ pagination: {
31
+ type: [Object, Boolean],
32
+ default: () => false,
33
+ },
34
+ });
35
+ // 如果传高度了,就用传的高度
36
+ // 如果没传高度,考虑带分页和不带分页两种情况
37
+ const tableHeight = computed(() => {
38
+ if (props.height) {
39
+ return props.height;
40
+ } else {
41
+ if (props.pagination) {
42
+ return "calc(100vh - 141px)";
43
+ } else {
44
+ return "calc(100vh - 77px)";
45
+ }
46
+ }
47
+ });
48
+ </script>
@@ -0,0 +1,160 @@
1
+ <!--
2
+ 图片上传 单个 多个
3
+ @author zhl
4
+ @date 2026/03/11
5
+ -->
6
+ <template>
7
+ <a-upload
8
+ :disabled="props.disabled"
9
+ list-type="picture-card"
10
+ :file-list="showUploadList"
11
+ :action="requestUrl"
12
+ :accept="props.fileType"
13
+ :headers="props.headers"
14
+ :data="props.data"
15
+ :before-upload="beforeUpload"
16
+ :on-success="onSuccess"
17
+ :on-error="onError"
18
+ @remove="removeImg"
19
+ @preview="handlePreview"
20
+ >
21
+ <template v-if="!disabled">
22
+ <template v-if="showUploadList.length < imgLimit">
23
+ <LoadingOutlined v-if="state.loading" />
24
+ <plus-outlined v-else />
25
+ </template>
26
+ </template>
27
+ </a-upload>
28
+ <a-modal
29
+ :open="state.showModal"
30
+ title="预览"
31
+ :footer="null"
32
+ @cancel="state.showModal = false"
33
+ >
34
+ <img alt="example" style="width: 100%" :src="state.showImgUrl" />
35
+ </a-modal>
36
+ </template>
37
+ <script setup lang="ts">
38
+ import { message } from "ant-design-vue";
39
+ import { PlusOutlined, LoadingOutlined } from "@ant-design/icons-vue";
40
+ import { reactive, computed } from "vue";
41
+ import { URL } from "@/utils/request";
42
+
43
+ const emits = defineEmits([
44
+ "update:modelValue",
45
+ "onSuccess",
46
+ "getImgUrl",
47
+ "beforeUpload",
48
+ ]);
49
+ /**
50
+ * 传递参数
51
+ * @params modelValue 绑定值 单个 或 多个
52
+ * @params disabled 是否禁用
53
+ * @params requestUrl 请求地址
54
+ * @params headers 头部参数
55
+ * @params data 更多参数
56
+ * @params fileType 选择图片类型 默认所有格式图片
57
+ */
58
+ const props = defineProps({
59
+ modelValue: {},
60
+ disabled: {
61
+ type: Boolean,
62
+ },
63
+ imgLimit: {
64
+ type: Number,
65
+ default: () => 1,
66
+ },
67
+ data: {
68
+ type: Object,
69
+ },
70
+ fileType: {
71
+ type: String,
72
+ default: () => "image/*",
73
+ },
74
+ headers: { type: Object },
75
+ requestUrl: {
76
+ type: String,
77
+ },
78
+ });
79
+ const state = reactive({
80
+ loading: false,
81
+ showImgUrl: "",
82
+ showModal: false,
83
+ });
84
+ const handlePreview = async (file) => {
85
+ state.showImgUrl = file.url;
86
+ state.showModal = true;
87
+ };
88
+ /**
89
+ * 是否显示上传列表
90
+ * 单图片 多图片显示
91
+ * @author zhl
92
+ * @date 2023/12/08
93
+ */
94
+ const showUploadList = computed(() => {
95
+ if (typeof props.modelValue === "string") {
96
+ if (props.modelValue) {
97
+ return [{ url: props.modelValue }];
98
+ } else {
99
+ return [];
100
+ }
101
+ } else {
102
+ return props.modelValue.map((item) => {
103
+ return { url: item };
104
+ });
105
+ }
106
+ });
107
+ /**
108
+ * 上传前
109
+ * @author zhl
110
+ * @date 2023/12/06
111
+ */
112
+ const beforeUpload = (file) => {
113
+ state.loading = true;
114
+ emits("beforeUpload", file);
115
+ return true;
116
+ };
117
+ /**
118
+ * 上传成功
119
+ * @author zhl
120
+ * @date 2023/12/06
121
+ */
122
+ const onSuccess = (res) => {
123
+ state.loading = false;
124
+ if (res.code == 200) {
125
+ if (props.imgLimit > 1) {
126
+ // let data = JSON.parse(JSON.stringify(props.modelValue))
127
+ // data.push(res.data.url)
128
+ // emits('update:modelValue', data)
129
+ props.modelValue.push(res.data.url);
130
+ } else {
131
+ emits("update:modelValue", res.data.url);
132
+ emits("getImgUrl", res.data.url);
133
+ }
134
+ } else {
135
+ message.error(res.msg);
136
+ }
137
+ };
138
+ /**
139
+ * 上传失败
140
+ * @author zhl
141
+ * @date 2023/12/06
142
+ */
143
+ const onError = () => {
144
+ state.loading = false;
145
+ message.error("上传失败");
146
+ };
147
+ const removeImg = (file) => {
148
+ if (props.imgLimit > 1) {
149
+ showUploadList.value.forEach((item, index) => {
150
+ if (item.url == file.url) {
151
+ showUploadList.value.splice(index, 1);
152
+ props.modelValue.splice(index, 1);
153
+ }
154
+ });
155
+ } else {
156
+ emits("update:modelValue", "");
157
+ }
158
+ };
159
+ </script>
160
+ <style lang="scss"></style>
@@ -0,0 +1,5 @@
1
+ .ant-modal-body {
2
+ max-height: 80vh;
3
+ overflow-y: auto;
4
+ overflow-x: hidden;
5
+ }
@@ -0,0 +1,75 @@
1
+ <!--
2
+ 弹窗
3
+ @author zhl
4
+ @date 2026/03/11
5
+ -->
6
+ <template>
7
+ <vxe-modal
8
+ :title="props.title"
9
+ v-model="state.showModal"
10
+ :loading="state.loading"
11
+ maskClosable
12
+ escClosable
13
+ :height="props.height"
14
+ :width="props.width"
15
+ :showFooter="props.showFooter"
16
+ show-cancel-button
17
+ show-confirm-button
18
+ destroy-on-close
19
+ :confirm-closable="false"
20
+ @confirm="emits('confirm')"
21
+ @cancel="emits('close')"
22
+ @close="emits('close')"
23
+ >
24
+ <slot></slot>
25
+ </vxe-modal>
26
+ </template>
27
+ <script setup lang="ts">
28
+ import { VxeModal } from "vxe-pc-ui";
29
+ import { reactive } from "vue";
30
+
31
+ const emits = defineEmits(["confirm", "close"]);
32
+ /**
33
+ * @params title 弹窗显示标题
34
+ * @params width 弹窗宽度 字符串 100px 100 100% 50vw calc(50vw - 50px)
35
+ * @params height 弹窗宽度 字符串 100px 100 100% 50vh calc(50vh - 50px)
36
+ * @params maskClosable 是否允许点击遮罩层关闭窗口
37
+ * @params escClosable 是否允许按 Esc 键关闭窗口
38
+ * @params showFooter 是否显示底部按钮 自定义footer会直接覆盖默认footer
39
+ */
40
+ const props = defineProps({
41
+ title: { type: String },
42
+ width: { type: String },
43
+ height: { type: String },
44
+ maskClosable: {
45
+ type: Boolean,
46
+ default: () => true,
47
+ },
48
+ escClosable: {
49
+ type: Boolean,
50
+ default: () => true,
51
+ },
52
+ showFooter: {
53
+ type: Boolean,
54
+ default: () => true,
55
+ },
56
+ });
57
+ const state = reactive({
58
+ loading: false,
59
+ showModal: false,
60
+ });
61
+ const open = () => {
62
+ state.showModal = true;
63
+ };
64
+ const close = () => {
65
+ state.showModal = false;
66
+ };
67
+ const setLoading = (loading: boolean) => {
68
+ state.loading = loading;
69
+ };
70
+ defineExpose({
71
+ open,
72
+ close,
73
+ setLoading,
74
+ });
75
+ </script>
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "zhl-methods",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "license": "ISC",
5
5
  "dependencies": {
6
- "dayjs": "^1.11.15",
7
- "vue": "^3.5.12"
6
+ "dayjs": "^1.11.15"
8
7
  }
9
8
  }