@2kog/pkg-widget 0.1.9
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.
- package/.editorconfig +13 -0
- package/.env +10 -0
- package/.vscode/extensions.json +3 -0
- package/README.md +11 -0
- package/index.html +13 -0
- package/package.json +37 -0
- package/public/favicon.ico +0 -0
- package/src/App.vue +55 -0
- package/src/assets/css/app.less +1 -0
- package/src/assets/css/component/upload-image.less +80 -0
- package/src/assets/css/mixin.less +20 -0
- package/src/assets/css/var.less +40 -0
- package/src/assets/css/widget.less +43 -0
- package/src/assets/data/upload.js +12 -0
- package/src/assets/img/earth.svg +1 -0
- package/src/assets/img/logo/iruxu.svg +8 -0
- package/src/assets/img/pay/alipay.svg +1 -0
- package/src/assets/img/pay/wepay.svg +1 -0
- package/src/assets/img/trash.svg +1 -0
- package/src/components/common/card-header.vue +48 -0
- package/src/components/common/lang-select.vue +144 -0
- package/src/components/common/logo.vue +57 -0
- package/src/components/common/pay.vue +837 -0
- package/src/components/common/phone-code-select.vue +104 -0
- package/src/components/common/upload-image.vue +138 -0
- package/src/demo/pay-dialog-demo.vue +133 -0
- package/src/locale/en-us/index.js +39 -0
- package/src/locale/index.js +31 -0
- package/src/locale/zh-cn/index.js +39 -0
- package/src/main.js +18 -0
- package/vite.config.js +29 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-select
|
|
3
|
+
v-model="select"
|
|
4
|
+
filterable
|
|
5
|
+
:filter-method="filterMethod"
|
|
6
|
+
class="w-phonecode-select"
|
|
7
|
+
popper-class="w-phonecode-select__pop"
|
|
8
|
+
style="width: 200px"
|
|
9
|
+
placeholder=""
|
|
10
|
+
>
|
|
11
|
+
<el-option
|
|
12
|
+
v-for="country in filterData"
|
|
13
|
+
:key="country.iso2"
|
|
14
|
+
:label="country.name"
|
|
15
|
+
:value="country.dialCode"
|
|
16
|
+
>
|
|
17
|
+
<span class="fi" :class="`fi-${country.iso2}`"></span>
|
|
18
|
+
<span class="u-country">{{ country.name }} <span class="u-dial">(+{{ country.dialCode }})</span></span>
|
|
19
|
+
</el-option>
|
|
20
|
+
|
|
21
|
+
<template #label>
|
|
22
|
+
<div class="m-label">
|
|
23
|
+
<span class="fi" :class="`fi-${country?.iso2}`"></span>
|
|
24
|
+
<span class="u-dial">(+{{ country?.dialCode }})</span>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
</el-select>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script>
|
|
31
|
+
import "flag-icons/css/flag-icons.min.css";
|
|
32
|
+
import intlTelInput from "intl-tel-input";
|
|
33
|
+
|
|
34
|
+
export default {
|
|
35
|
+
name: "CountryPhonecode",
|
|
36
|
+
props: {
|
|
37
|
+
modelValue: {
|
|
38
|
+
type: [Number, String],
|
|
39
|
+
default: "",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
emits: ["update:modelValue"],
|
|
43
|
+
data() {
|
|
44
|
+
return {
|
|
45
|
+
countryData: [],
|
|
46
|
+
filterData: [],
|
|
47
|
+
select: ""
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
computed: {
|
|
51
|
+
country() {
|
|
52
|
+
return this.countryData?.find(
|
|
53
|
+
(item) => item.dialCode == this.select
|
|
54
|
+
) || {}
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
watch: {
|
|
58
|
+
select(val) {
|
|
59
|
+
this.$emit("update:modelValue", val);
|
|
60
|
+
},
|
|
61
|
+
modelValue: {
|
|
62
|
+
handler(val) {
|
|
63
|
+
this.select = val;
|
|
64
|
+
},
|
|
65
|
+
immediate: true,
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
mounted() {
|
|
69
|
+
this.countryData = intlTelInput.getCountryData();
|
|
70
|
+
this.filterData = this.countryData;
|
|
71
|
+
},
|
|
72
|
+
methods: {
|
|
73
|
+
filterMethod(query) {
|
|
74
|
+
if (query !== "") {
|
|
75
|
+
this.filterData = this.countryData.filter((item) => {
|
|
76
|
+
return (item.name
|
|
77
|
+
.toLowerCase()
|
|
78
|
+
.includes(query.toLowerCase()) || item.dialCode.includes(query));
|
|
79
|
+
});
|
|
80
|
+
} else {
|
|
81
|
+
this.filterData = this.countryData;
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<style lang="less">
|
|
89
|
+
.w-phonecode-select {
|
|
90
|
+
.m-label {
|
|
91
|
+
.flex;
|
|
92
|
+
align-content: center;
|
|
93
|
+
gap: 5px;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
.w-phonecode-select__pop {
|
|
97
|
+
.u-country {
|
|
98
|
+
margin-left: 10px;
|
|
99
|
+
}
|
|
100
|
+
.u-dial {
|
|
101
|
+
color: #999;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
</style>
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-upload-image">
|
|
3
|
+
<div
|
|
4
|
+
v-if="data"
|
|
5
|
+
class="u-image"
|
|
6
|
+
:style="{ width, height }"
|
|
7
|
+
:class="{ 'is-circle': isCircle }"
|
|
8
|
+
>
|
|
9
|
+
<img class="u-image-pic" :src="data" />
|
|
10
|
+
<i class="u-image-mask"></i>
|
|
11
|
+
<i class="u-image-delete" title="移除" @click="remove"
|
|
12
|
+
><img src="../../assets/img/trash.svg" alt="移除"
|
|
13
|
+
/></i>
|
|
14
|
+
</div>
|
|
15
|
+
<div v-else class="u-upload" :class="{ 'is-circle': isCircle }" @click="select" :style="{ width, height }" v-loading="loading">
|
|
16
|
+
<i class="u-upload-icon">+</i>
|
|
17
|
+
</div>
|
|
18
|
+
<input
|
|
19
|
+
class="u-upload-input"
|
|
20
|
+
type="file"
|
|
21
|
+
@change="add"
|
|
22
|
+
ref="uploadInput"
|
|
23
|
+
:accept="accept"
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script>
|
|
29
|
+
import {buildOssSuffix} from "@2kog/pkg-common/utils/common";
|
|
30
|
+
import cloneDeep from "lodash/cloneDeep";
|
|
31
|
+
export default {
|
|
32
|
+
name: "UploadImage",
|
|
33
|
+
props: {
|
|
34
|
+
// 图片地址
|
|
35
|
+
url: {
|
|
36
|
+
type: String,
|
|
37
|
+
default: "",
|
|
38
|
+
},
|
|
39
|
+
defaultAvatar: {
|
|
40
|
+
type: String,
|
|
41
|
+
required: false,
|
|
42
|
+
default: "",
|
|
43
|
+
},
|
|
44
|
+
size: {
|
|
45
|
+
type: Array,
|
|
46
|
+
default: [120, 120],
|
|
47
|
+
},
|
|
48
|
+
shape: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: "square",
|
|
51
|
+
},
|
|
52
|
+
uploadFn: {
|
|
53
|
+
type: Function,
|
|
54
|
+
default: () => {},
|
|
55
|
+
required: true,
|
|
56
|
+
},
|
|
57
|
+
domain: {
|
|
58
|
+
type: String,
|
|
59
|
+
default: "",
|
|
60
|
+
required: true,
|
|
61
|
+
},
|
|
62
|
+
accept: {
|
|
63
|
+
type: Array,
|
|
64
|
+
default: () => [
|
|
65
|
+
".jpg",
|
|
66
|
+
".jpeg",
|
|
67
|
+
".png",
|
|
68
|
+
".gif",
|
|
69
|
+
".bmp",
|
|
70
|
+
".webp",
|
|
71
|
+
".heic",
|
|
72
|
+
".heif",
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
data() {
|
|
77
|
+
return {
|
|
78
|
+
data: "",
|
|
79
|
+
file: null,
|
|
80
|
+
|
|
81
|
+
loading: false,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
computed: {
|
|
85
|
+
isCircle() {
|
|
86
|
+
return this.shape === "circle";
|
|
87
|
+
},
|
|
88
|
+
width() {
|
|
89
|
+
return this.size[0] + "px";
|
|
90
|
+
},
|
|
91
|
+
height() {
|
|
92
|
+
return this.size[1] + "px";
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
watch: {
|
|
96
|
+
url: {
|
|
97
|
+
handler: function (val) {
|
|
98
|
+
this.data = val && this.getAvatar(this.domain + val) || cloneDeep(this.defaultAvatar);
|
|
99
|
+
},
|
|
100
|
+
immediate: true,
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
methods: {
|
|
104
|
+
select: function () {
|
|
105
|
+
this.$refs.uploadInput.dispatchEvent(new MouseEvent("click"));
|
|
106
|
+
},
|
|
107
|
+
getAvatar(url) {
|
|
108
|
+
const size = this.size.map(item => item * 2)
|
|
109
|
+
return url ? url + buildOssSuffix(size) : "";
|
|
110
|
+
},
|
|
111
|
+
add: function (e) {
|
|
112
|
+
this.file = e.target.files[0];
|
|
113
|
+
// this.data = window.URL.createObjectURL(this.file);
|
|
114
|
+
// this.$emit("update", this.file);
|
|
115
|
+
this.loading = true;
|
|
116
|
+
this.uploadFn(this.file)
|
|
117
|
+
.then((res) => {
|
|
118
|
+
this.data = this.getAvatar(this.domain + res.data.data);
|
|
119
|
+
this.$emit("update", res.data.data);
|
|
120
|
+
})
|
|
121
|
+
.finally(() => {
|
|
122
|
+
this.loading = false;
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
remove: function () {
|
|
126
|
+
this.$refs.uploadInput.value = "";
|
|
127
|
+
this.data = "";
|
|
128
|
+
this.data.startsWith("blob:") &&
|
|
129
|
+
window.URL.revokeObjectURL(this.data);
|
|
130
|
+
this.$emit("update", "");
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
</script>
|
|
135
|
+
|
|
136
|
+
<style lang="less">
|
|
137
|
+
@import "../../assets/css/component/upload-image.less";
|
|
138
|
+
</style>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<!-- 支付弹窗组件使用示例 -->
|
|
2
|
+
<template>
|
|
3
|
+
<div class="demo">
|
|
4
|
+
<h1>支付弹窗组件演示</h1>
|
|
5
|
+
|
|
6
|
+
<el-button type="primary" @click="openPayDialog">打开支付弹窗(支付宝)</el-button>
|
|
7
|
+
<el-button type="success" @click="openWepayDialog" style="margin-left: 10px;">打开支付弹窗(微信)</el-button>
|
|
8
|
+
|
|
9
|
+
<!-- 支付弹窗 -->
|
|
10
|
+
<Payment
|
|
11
|
+
v-model="payVisible"
|
|
12
|
+
title="支付中心"
|
|
13
|
+
width="50%"
|
|
14
|
+
:product-id="productId"
|
|
15
|
+
:count="count"
|
|
16
|
+
:product-desc="productDesc"
|
|
17
|
+
:pay-mode="payMode"
|
|
18
|
+
:return-url="'/order/success'"
|
|
19
|
+
:api-request="handleApiRequest"
|
|
20
|
+
@done="onPaymentDone"
|
|
21
|
+
@cancel="onPaymentCancel"
|
|
22
|
+
@error="onError"
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
import Payment from '../components/common/pay.vue';
|
|
29
|
+
import axios from 'axios'; // 或者你的请求库
|
|
30
|
+
|
|
31
|
+
function $http(options = {}, axiosConfig = {}) {
|
|
32
|
+
// 解构options并设置默认值
|
|
33
|
+
const { interceptor = true, domain, region, progress } = options;
|
|
34
|
+
|
|
35
|
+
// 获取请求域名
|
|
36
|
+
let requestDomain = "";
|
|
37
|
+
if (domain) {
|
|
38
|
+
requestDomain = domain;
|
|
39
|
+
} else {
|
|
40
|
+
requestDomain = import.meta.env.VUE_APP_COMMON_API;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 设置请求头
|
|
44
|
+
let config = {
|
|
45
|
+
// 同时发送cookie和basic auth
|
|
46
|
+
withCredentials: true,
|
|
47
|
+
headers: {
|
|
48
|
+
Authorization: "Bearer " + localStorage.getItem("RX_Token"),
|
|
49
|
+
},
|
|
50
|
+
baseURL: requestDomain,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// 设置进度条
|
|
54
|
+
if (progress) {
|
|
55
|
+
config.onUploadProgress = progress;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 创建实例
|
|
59
|
+
const ins = axios.create(Object.assign(axiosConfig, config));
|
|
60
|
+
|
|
61
|
+
return ins;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default {
|
|
65
|
+
components: {
|
|
66
|
+
Payment,
|
|
67
|
+
},
|
|
68
|
+
data() {
|
|
69
|
+
return {
|
|
70
|
+
payVisible: false, // 支付弹窗显示状态
|
|
71
|
+
payMode: 'alipay', // 默认支付方式
|
|
72
|
+
productId: 1,
|
|
73
|
+
count: 1,
|
|
74
|
+
productDesc: 'VIP会员 - 年度套餐',
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
methods: {
|
|
78
|
+
// 打开支付弹窗(支付宝)
|
|
79
|
+
openPayDialog() {
|
|
80
|
+
this.payMode = 'alipay';
|
|
81
|
+
this.payVisible = true;
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
// 打开支付弹窗(微信)
|
|
85
|
+
openWepayDialog() {
|
|
86
|
+
this.payMode = 'wepay';
|
|
87
|
+
this.payVisible = true;
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
// API请求函数 - 适配你的项目
|
|
91
|
+
async handleApiRequest(url, method, data) {
|
|
92
|
+
try {
|
|
93
|
+
console.log(`API请求: ${method} ${url}`, data);
|
|
94
|
+
const response = await $http()[method.toLowerCase()](url, method === 'GET' ? { params: data } : data);
|
|
95
|
+
return response.data.data;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
// 支付完成
|
|
102
|
+
onPaymentDone(data) {
|
|
103
|
+
console.log('支付成功:', data);
|
|
104
|
+
this.$message?.success('支付成功!');
|
|
105
|
+
// 弹窗会自动关闭并刷新页面
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
// 取消支付
|
|
109
|
+
onPaymentCancel() {
|
|
110
|
+
console.log('用户取消支付');
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
// 错误处理
|
|
114
|
+
onError({ step, error }) {
|
|
115
|
+
console.error(`${step} 失败:`, error);
|
|
116
|
+
this.$message?.error(error.message || '操作失败');
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
</script>
|
|
121
|
+
|
|
122
|
+
<style scoped>
|
|
123
|
+
.demo {
|
|
124
|
+
max-width: 800px;
|
|
125
|
+
margin: 40px auto;
|
|
126
|
+
padding: 20px;
|
|
127
|
+
text-align: center;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
h1 {
|
|
131
|
+
margin-bottom: 40px;
|
|
132
|
+
}
|
|
133
|
+
</style>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
payment: {
|
|
3
|
+
title: 'Payment Center',
|
|
4
|
+
loading: 'Processing order...',
|
|
5
|
+
loadingCreate: 'Creating order...',
|
|
6
|
+
loadingQrcode: 'Generating QR code...',
|
|
7
|
+
loadingOrder: 'Processing order...',
|
|
8
|
+
success: 'Payment Successful!',
|
|
9
|
+
successDesc: 'Order completed, thank you for your purchase',
|
|
10
|
+
|
|
11
|
+
// Payment methods
|
|
12
|
+
alipay: 'Alipay',
|
|
13
|
+
alipayTip: 'Huabei installment supported',
|
|
14
|
+
wepay: 'WeChat Pay',
|
|
15
|
+
wepayTip: 'Credit card supported',
|
|
16
|
+
|
|
17
|
+
// Price
|
|
18
|
+
currency: 'CNY',
|
|
19
|
+
|
|
20
|
+
// Tips
|
|
21
|
+
pcAlipay: 'Mobile device not available? Use ',
|
|
22
|
+
pcAlipayLink: 'PC version Alipay',
|
|
23
|
+
pcAlipaySuffix: ' to pay.',
|
|
24
|
+
expireTip: '(Expires in 20 minutes, please click [Payment Completed] after payment)',
|
|
25
|
+
warningTitle: 'Order not paid or expired',
|
|
26
|
+
|
|
27
|
+
// Buttons
|
|
28
|
+
cancel: 'Cancel',
|
|
29
|
+
completed: 'Payment Completed',
|
|
30
|
+
|
|
31
|
+
// Error messages
|
|
32
|
+
invalidOrder: 'Invalid order number',
|
|
33
|
+
createOrderFailed: 'Failed to create order',
|
|
34
|
+
orderTimeout: 'Order processing timeout',
|
|
35
|
+
orderFailed: 'Order processing failed',
|
|
36
|
+
getQrcodeFailed: 'Failed to get payment QR code',
|
|
37
|
+
paymentTimeout: 'Payment timeout',
|
|
38
|
+
}
|
|
39
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createI18n } from "vue-i18n";
|
|
2
|
+
|
|
3
|
+
const getLocale = () => {
|
|
4
|
+
const _val = localStorage.getItem('lang');
|
|
5
|
+
if (!_val) {
|
|
6
|
+
return navigator.language;
|
|
7
|
+
} else {
|
|
8
|
+
return _val;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// 1. Ready translated locale messages
|
|
13
|
+
// The structure of the locale message is the hierarchical object structure with each locale as the top property
|
|
14
|
+
import enUs from "./en-us";
|
|
15
|
+
import zhCn from "./zh-cn";
|
|
16
|
+
const lang = {
|
|
17
|
+
"en-US": enUs,
|
|
18
|
+
"zh-CN": zhCn,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// 2. Create i18n instance with options
|
|
22
|
+
const i18n = createI18n({
|
|
23
|
+
locale: getLocale(), // set locale
|
|
24
|
+
fallbackLocale: "zh-CN", // set fallback locale
|
|
25
|
+
messages: lang, // set locale messages
|
|
26
|
+
// If you need to specify other options, you can set other options
|
|
27
|
+
// ...
|
|
28
|
+
warnHtmlInMessage: "off",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export { i18n };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
payment: {
|
|
3
|
+
title: '支付中心',
|
|
4
|
+
loading: '正在处理订单...',
|
|
5
|
+
loadingCreate: '正在创建订单...',
|
|
6
|
+
loadingQrcode: '正在生成二维码...',
|
|
7
|
+
loadingOrder: '正在处理订单...',
|
|
8
|
+
success: '支付成功!',
|
|
9
|
+
successDesc: '订单已完成,感谢您的购买',
|
|
10
|
+
|
|
11
|
+
// 支付方式
|
|
12
|
+
alipay: '支付宝支付',
|
|
13
|
+
alipayTip: '支持花呗分期',
|
|
14
|
+
wepay: '微信支付',
|
|
15
|
+
wepayTip: '支持信用卡',
|
|
16
|
+
|
|
17
|
+
// 价格
|
|
18
|
+
currency: '元',
|
|
19
|
+
|
|
20
|
+
// 提示
|
|
21
|
+
pcAlipay: '手机不在身边?使用',
|
|
22
|
+
pcAlipayLink: '电脑版支付宝',
|
|
23
|
+
pcAlipaySuffix: '支付。',
|
|
24
|
+
expireTip: '(20分钟过期,请在支付完成后点击【已完成支付】)',
|
|
25
|
+
warningTitle: '订单尚未支付或已过期',
|
|
26
|
+
|
|
27
|
+
// 按钮
|
|
28
|
+
cancel: '取消',
|
|
29
|
+
completed: '已完成支付',
|
|
30
|
+
|
|
31
|
+
// 错误提示
|
|
32
|
+
invalidOrder: '无效订单号',
|
|
33
|
+
createOrderFailed: '创建订单失败',
|
|
34
|
+
orderTimeout: '订单处理超时',
|
|
35
|
+
orderFailed: '订单处理失败',
|
|
36
|
+
getQrcodeFailed: '获取支付二维码失败',
|
|
37
|
+
paymentTimeout: '支付超时',
|
|
38
|
+
}
|
|
39
|
+
};
|
package/src/main.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createApp } from 'vue'
|
|
2
|
+
import App from './App.vue'
|
|
3
|
+
|
|
4
|
+
const app = createApp(App);
|
|
5
|
+
|
|
6
|
+
import { i18n } from "./locale";
|
|
7
|
+
app.use(i18n);
|
|
8
|
+
|
|
9
|
+
import ElementPlus from "element-plus";
|
|
10
|
+
import "element-plus/dist/index.css";
|
|
11
|
+
app.use(ElementPlus);
|
|
12
|
+
|
|
13
|
+
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
|
|
14
|
+
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
15
|
+
app.component(key, component);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
app.mount('#app')
|
package/vite.config.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import vue from "@vitejs/plugin-vue";
|
|
3
|
+
import vitePluginRequire from "vite-plugin-require";
|
|
4
|
+
|
|
5
|
+
// https://vitejs.dev/config/
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
plugins: [vue(), vitePluginRequire.default()],
|
|
8
|
+
server: {
|
|
9
|
+
proxy: {
|
|
10
|
+
'/api': {
|
|
11
|
+
target: 'https://pay.dpying.com',
|
|
12
|
+
changeOrigin: true,
|
|
13
|
+
secure: false,
|
|
14
|
+
// 不需要 rewrite,保持完整路径
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
css: {
|
|
19
|
+
preprocessorOptions: {
|
|
20
|
+
less: {
|
|
21
|
+
additionalData: `
|
|
22
|
+
@import "./node_modules/csslab/base.less";
|
|
23
|
+
@import "./node_modules/csslab/reset.less";
|
|
24
|
+
@import "./src/assets/css/var.less";
|
|
25
|
+
`,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|