commit 242f834edbbdcf9de184721bfead2ebe6b5cf4be Author: elf <360197197@qq.com> Date: Mon Jul 15 23:01:30 2024 +0800 yh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc51bea --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.history +vite.config.ts.timestamp* diff --git a/README.md b/README.md new file mode 100644 index 0000000..e0acb37 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Vue 3 + Vite + +This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` + + + + diff --git a/src/components/IPC.vue b/src/components/IPC.vue new file mode 100644 index 0000000..8fe4f86 --- /dev/null +++ b/src/components/IPC.vue @@ -0,0 +1,8 @@ + diff --git a/src/constant/common.ts b/src/constant/common.ts new file mode 100644 index 0000000..9c16b88 --- /dev/null +++ b/src/constant/common.ts @@ -0,0 +1,49 @@ +// good +import { defineConstants } from '@/utils/constant'; + +export const { TOGGLE, TOGGLE_MAP, TOGGLE_LIST } = defineConstants( + [ + { key: '1', keyAlias: 'yes', label: '是' }, + { key: '0', keyAlias: 'no', label: '否' }, + ] as const, + 'TOGGLE', + 'key', + 'keyAlias', +); +export const TOGGLE_SWITCH_LIST = [ + { ...TOGGLE_LIST[0], label: '开启' }, + { ...TOGGLE_LIST[1], label: '关闭' }, +] as const; +export type ToggleEnum = ValueOf; +export type ToggleEnumWithNone = ToggleEnum | ''; + +export const { TOGGLE_EN, TOGGLE_EN_MAP, TOGGLE_EN_LIST } = defineConstants( + [ + { key: 'yes', label: '是' }, + { key: 'no', label: '否' }, + ] as const, + 'TOGGLE_EN', +); +export type ToggleEnEnum = ValueOf; +export type ToggleEnEnumWithNone = ToggleEnEnum | ''; + +export const { TOGGLE_NUM, TOGGLE_NUM_MAP, TOGGLE_NUM_LIST } = defineConstants( + [ + { key: 1, keyAlias: 'yes', label: '是' }, + { key: 0, keyAlias: 'no', label: '否' }, + ] as const, + 'TOGGLE_NUM', + 'key', + 'keyAlias', +); +export type ToggleNumEnum = ValueOf; + +export const { RESULT, RESULT_MAP, RESULT_LIST } = defineConstants( + [ + { key: 'fail', label: '失败' }, + { key: 'success', label: '成功' }, + ] as const, + 'RESULT', +); +export type ResultEnum = ValueOf; +export type ResultEnumWithNone = ResultEnum | ''; diff --git a/src/constant/request.ts b/src/constant/request.ts new file mode 100644 index 0000000..b74000d --- /dev/null +++ b/src/constant/request.ts @@ -0,0 +1,28 @@ +// good +import { defineConstants } from '../utils/constant'; + +export const REQUEST_BASE_URL = '/api'; + +export const { REQUEST_CODE, REQUEST_CODE_MAP, REQUEST_CODE_LIST } = defineConstants( + [ + { key: '0000', label: '成功', keyAlias: 'success' }, + { key: '1000', label: '登录过期', keyAlias: 'expired' }, + ], + 'REQUEST_CODE', + 'key', + 'keyAlias', +); +export type RequestCodeEnum = ValueOf; + +export const { REQUEST_CONTENT_TYPE, REQUEST_CONTENT_TYPE_MAP, REQUEST_CONTENT_TYPE_LIST } = defineConstants( + [ + { key: 'text/html', keyAlias: 'html' }, + { key: 'application/json', keyAlias: 'json' }, + { key: 'application/x-www-form-urlencoded', keyAlias: 'formUrl' }, + { key: 'multipart/form-data', keyAlias: 'formData' }, + { key: 'application/vnd.ms-excel', keyAlias: 'excel' }, + ] as const, + 'REQUEST_CONTENT_TYPE', + 'key', + 'keyAlias', +); diff --git a/src/hooks/index.ts b/src/hooks/index.ts new file mode 100644 index 0000000..a8c3cc2 --- /dev/null +++ b/src/hooks/index.ts @@ -0,0 +1 @@ +export * from './useLoading'; diff --git a/src/hooks/useLoading/index.ts b/src/hooks/useLoading/index.ts new file mode 100644 index 0000000..d4cd5ca --- /dev/null +++ b/src/hooks/useLoading/index.ts @@ -0,0 +1,48 @@ +import { ElLoading } from 'element-plus'; +import { ref, isRef, nextTick } from 'vue'; +import type { LoadingOptions } from 'element-plus'; + +type OverwriteLoadingOptions = Omit & { + isSync?: boolean; + target?: Ref | HTMLElement | string; +}; + +const defaultOptions: LoadingOptions = { + text: '', + background: 'rgba(0, 0, 0, 0.5)', +}; + +export function useLoading(options: OverwriteLoadingOptions = { isSync: false }) { + const config = { ...defaultOptions, ...options }; + const loading = ref(false); + const loadingInstance = ref>(); + + // 支持 Ref + const { target } = config; + if (target && isRef(target)) { + nextTick(() => { + config.target = target.value; + }); + } + + const openLoading = () => { + if (loading.value) return; + + loading.value = true; + loadingInstance.value = ElLoading.service(config as LoadingOptions); + }; + + const closeLoading = (isSync = false) => { + if (!loading.value) return; + + loading.value = false; + loadingInstance.value?.close(); + (isSync || options.isSync) && loadingInstance.value?.removeElLoadingChild(); + }; + + return { + loading, + openLoading, + closeLoading, + }; +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..e5af8ea --- /dev/null +++ b/src/main.ts @@ -0,0 +1,14 @@ +import { createApp } from 'vue'; +import ElementPlus from 'element-plus'; + +import App from './App.vue'; +import router from '@/router'; +import './style.scss'; +import 'element-plus/theme-chalk/src/index.scss'; + +const mainApp = createApp(App); + +mainApp.use(ElementPlus); +mainApp.use(router); + +mainApp.mount('#app'); diff --git a/src/router/constantRoutes.ts b/src/router/constantRoutes.ts new file mode 100644 index 0000000..d265547 --- /dev/null +++ b/src/router/constantRoutes.ts @@ -0,0 +1,27 @@ +// good +export default [ + { + path: '/', + component: () => import('@/views/404/index.vue'), + }, + { + name: 'Sign', + path: '/sign', + component: () => import('@/views/sign/index.vue'), + }, + { + name: 'Tender', + path: '/tender', + component: () => import('@/views/tender/index.vue'), + }, + { + name: 'Callback', + path: '/callback', + component: () => import('@/views/callback/index.vue'), + }, + { + name: 'NotFound', + path: '/:pathMatch(.*)*', + component: () => import('@/views/404/index.vue'), + }, +]; diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..705eb40 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,11 @@ +import { createRouter, createWebHistory } from 'vue-router'; + +import routes from './constantRoutes'; + +const router = createRouter({ + history: createWebHistory(), + scrollBehavior: () => ({ top: 0 }), + routes, +}); + +export default router; diff --git a/src/style.scss b/src/style.scss new file mode 100644 index 0000000..efd30db --- /dev/null +++ b/src/style.scss @@ -0,0 +1,347 @@ +html, +body { + margin: 0; + padding: 0; + height: 100vh; + overflow: auto; + background-color: #eff2f9; +} + +.color-warn { + color: #ff8834; +} + +.color-danger { + color: #f45057; +} + +.color-placeholder { + color: #909399; +} + +.select-none { + user-select: none; +} + +.position-center { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.single-ellipsis { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.multiple-ellipsis { + word-break: break-all; + white-space: pre-wrap; + display: -webkit-box; + -webkit-line-clamp: 2; + overflow: hidden; + -webkit-box-orient: vertical; +} + +.white-space-nowrap { + white-space: nowrap; +} + +.visibility-hidden { + opacity: 0; + pointer-events: none; +} + +@for $i from 0 through 100 { + .m-#{$i} { + margin: $i + px !important; + } + + .m-t-#{$i} { + margin-top: $i + px !important; + } + + .m-b-#{$i} { + margin-bottom: $i + px !important; + } + + .m-l-#{$i} { + margin-left: $i + px !important; + } + + .m-r-#{$i} { + margin-right: $i + px !important; + } + + .m-x-#{$i} { + margin-left: $i + px !important; + margin-right: $i + px !important; + } + + .m-y-#{$i} { + margin-top: $i + px !important; + margin-bottom: $i + px !important; + } + + .p-#{$i} { + padding: $i + px !important; + } + + .p-t-#{$i} { + padding-top: $i + px !important; + } + + .p-b-#{$i} { + padding-bottom: $i + px !important; + } + + .p-l-#{$i} { + padding-left: $i + px !important; + } + + .p-r-#{$i} { + padding-right: $i + px !important; + } + + .p-x-#{$i} { + padding-left: $i + px !important; + padding-right: $i + px !important; + } + + .p-y-#{$i} { + padding-top: $i + px !important; + padding-bottom: $i + px !important; + } +} + +@for $i from 12 through 40 { + .ft-#{$i} { + font-size: $i + px !important; + } + + .line-height-#{$i} { + line-height: $i + px !important; + } +} + +$positionMap: ( + fixed: fixed, + static: static, + sticky: sticky, + relative: relative, + absolute: absolute, +); +@each $key, $val in $positionMap { + .pos-#{$key} { + position: $val; + } +} + +$displayMap: ( + none: none, + flex: flex, + inline-flex: inline-flex, + inline: inline, + block: block, + inline-block: inline-block, +); +@each $key, $val in $displayMap { + .d-#{$key} { + display: $val; + } +} + +.flex-1 { + flex: 1; +} + +$flexScaleAttrList: grow, shrink; +@each $scaleAttr in $flexScaleAttrList { + .flex-#{$scaleAttr}-0 { + flex-#{$scaleAttr}: 0; + } + + .flex-#{$scaleAttr}-1 { + flex-#{$scaleAttr}: 1; + } +} + +$flexAlignMap: ( + end: flex-end, + start: flex-start, + center: center, +); +@each $key, $val in $flexAlignMap { + .align-self-#{$key} { + align-self: $val !important; + } + + .align-items-#{$key} { + align-items: $val !important; + } +} + +$flexJustifyMap: ( + end: flex-end, + start: flex-start, + center: center, + around: space-around, + between: space-between, +); +@each $key, $val in $flexJustifyMap { + .justify-self-#{$key} { + justify-self: $val !important; + } + + .justify-content-#{$key} { + justify-content: $val !important; + } +} + +$flexWrapMap: ( + wrap: wrap, + nowrap: nowrap, +); +@each $key, $val in $flexWrapMap { + .flex-#{$key} { + flex-wrap: $val !important; + } +} + +$flexDirectionMap: ( + row: row, + column: column, +); +@each $key, $val in $flexDirectionMap { + .flex-direction-#{$key} { + flex-direction: $val !important; + } +} + +$flexGapList: 4, 8, 12, 16, 20, 24; +@each $flexGap in $flexGapList { + .flex-gap-#{$flexGap} { + gap: $flexGap + px; + } +} + +$boxSizeAttrMap: ( + m: margin, + p: padding, + w: width, + h: height, +); +@each $key, $val in $boxSizeAttrMap { + .#{$key}-auto { + #{$val}: auto !important; + } + + .#{$key}-full { + #{$val}: 100% !important; + } + + @if $key == 'm' { + .#{$key}-l-auto { + #{$val}-left: auto !important; + } + .#{$key}-r-auto { + #{$val}-right: auto !important; + } + } +} + +$textAlignMap: ( + l: left, + r: right, + c: center, +); +@each $key, $val in $textAlignMap { + .text-align-#{$key} { + text-align: $val; + } +} + +$fontWeightMap: ( + bold: bold, + normal: normal, +); +@each $key, $val in $fontWeightMap { + .font-weight-#{$key} { + font-weight: $val; + } +} + +$wordBreakMap: ( + all: break-all, + normal: normal, +); +@each $key, $val in $wordBreakMap { + .word-break-#{$key} { + word-break: $val; + } +} + +$verticalAlignMap: ( + top: top, + sub: sub, + middle: middle, + bottom: bottom, +); +@each $key, $val in $verticalAlignMap { + .vertical-align-#{$key} { + vertical-align: $val; + } +} + +$decorationMap: ( + none: none, + under: underline, +); +@each $key, $val in $decorationMap { + .text-decoration-#{$key} { + text-decoration: $val; + } +} + +$overflowMap: ( + auto: auto, + hidden: hidden, +); +@each $key, $val in $overflowMap { + .overflow-#{$key} { + overflow: $val; + } + + .overflow-x-#{$key} { + overflow-x: $val; + } + + .overflow-y-#{$key} { + overflow-y: $val; + } +} + +$cursorMap: ( + move: move, + default: default, + pointer: pointer, + no-drop: no-drop, + disable: not-allowed, +); +@each $key, $val in $cursorMap { + .cursor-#{$key} { + cursor: $val; + } +} + +$eventsMap: ( + all: all, + none: none, +); +@each $key, $val in $eventsMap { + .events-#{$key} { + pointer-events: $val; + } +} diff --git a/src/utils/alert.ts b/src/utils/alert.ts new file mode 100644 index 0000000..bf2dfb6 --- /dev/null +++ b/src/utils/alert.ts @@ -0,0 +1,26 @@ +// good +import { ElMessage } from 'element-plus'; + +import type { Message } from 'element-plus'; + +type AlertTypeEnum = Exclude; + +const baseAlert = (type: AlertTypeEnum, message: string) => { + ElMessage[type]({ message, grouping: true, dangerouslyUseHTMLString: true }); +}; + +export function infoAlert(message: string) { + baseAlert('info', message); +} + +export function errorAlert(message: string) { + baseAlert('error', message); +} + +export function warningAlert(message: string) { + baseAlert('warning', message); +} + +export function successAlert(message: string) { + baseAlert('success', message); +} diff --git a/src/utils/constant.ts b/src/utils/constant.ts new file mode 100644 index 0000000..46fdfe9 --- /dev/null +++ b/src/utils/constant.ts @@ -0,0 +1,112 @@ +import { snakeCase } from 'lodash-es'; + +// helper +type Map = Record; +type MapList = ReadonlyArray; +type Underline = '_'; +type NumString = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; +type MergeMap = A extends infer T ? { [Key in keyof T]: T[Key] } : never; +// list to map +type ListToMap = T['length'] extends 0 + ? ACC + : T extends readonly [infer F extends Map, ...infer REST extends MapList] + ? ListToMap< + REST, + K, + ACC & { + readonly [Key in F[K]]: F; + } + > + : never; +type ListToKeyMap< + T extends MapList, + K extends keyof T[number], + KA extends keyof T[number], + ACC extends Map = object, +> = T['length'] extends 0 + ? ACC + : T extends readonly [infer F extends Map, ...infer REST extends MapList] + ? ListToKeyMap< + REST, + K, + KA, + ACC & { + readonly [Key in Uppercase>>]: F[K]; + } + > + : never; +// snakeCase +type SnakeCaseList = T['length'] extends 0 + ? ACC + : T extends [infer F extends string, ...infer REST extends string[]] + ? F extends '' + ? SnakeCaseList + : ACC extends '' + ? SnakeCaseList + : SnakeCaseList + : never; +type SnakeCaseString = []> = LIST extends [ + ...infer REST_LIST, +] + ? T extends '' + ? ACC extends '' + ? LIST + : [...REST_LIST, ACC] + : T extends `${infer F}${infer REST}` + ? F extends Underline + ? ACC extends '' + ? SnakeCaseString + : SnakeCaseString + : F extends NumString + ? ACC extends '' + ? SnakeCaseString + : GetFirstChar extends NumString + ? SnakeCaseString + : SnakeCaseString + : ACC extends '' + ? SnakeCaseString + : GetFirstChar extends NumString + ? SnakeCaseString + : F extends Uppercase + ? GetLastChar extends Uppercase> + ? SnakeCaseString + : SnakeCaseString + : SnakeCaseString + : never + : never; + +export function defineConstants< + T extends MapList, + N extends string, + K extends keyof T[number] = 'key', + KA extends keyof T[number] = K, +>(list: T, namespace: N, key: K = 'key' as K, keyAlias: KA = 'key' as KA) { + keyAlias = keyAlias || (key as unknown as KA); + + return { + [namespace]: list.reduce((keyMap, item) => { + const keyAliasVal = snakeCase(item[keyAlias]).toUpperCase(); + + keyMap[keyAliasVal] = item[key]; + + return keyMap; + }, {}), + + [namespace + '_MAP']: list.reduce((itemMap, item) => { + itemMap[item[key]] = item; + itemMap[item[keyAlias]] = item; + + return itemMap; + }, {}), + + [namespace + '_LIST']: list, + } as MergeMap< + { + [Key in N]: MergeMap>; + } & { + [Key in AddPrefix]: MergeMap & ListToMap>; + } & { + [Key in AddPrefix]: T; + } + >; +} diff --git a/src/utils/request.ts b/src/utils/request.ts new file mode 100644 index 0000000..3637b8d --- /dev/null +++ b/src/utils/request.ts @@ -0,0 +1,104 @@ +// good +import axios from 'axios'; +import { stringify } from 'qs'; +import { isNil, isEmpty, isObject } from 'lodash-es'; + +import { isQuery } from '@/utils/validate'; +import { errorAlert } from '@/utils/alert'; + +import { REQUEST_CODE, REQUEST_BASE_URL, REQUEST_CONTENT_TYPE } from '@/constant/request'; + +import type { RequestCodeEnum } from '@/constant/request'; +import type { AxiosResponse, AxiosRequestConfig } from 'axios'; + +const service = axios.create({ + baseURL: REQUEST_BASE_URL, + timeout: 5 * 60 * 1000, + headers: { 'Content-Type': REQUEST_CONTENT_TYPE.FORM_URL }, + withCredentials: true, +}); +service.interceptors.request.use(dealRequest, dealRejected); +service.interceptors.response.use(dealResponse, dealRejected); + +function dealRequest(config: AxiosRequestConfig) { + const { data, method, headers } = config; + + switch (method?.toUpperCase()) { + case 'GET': { + if (config.params) { + config.url = getUrlWithQuery(config.url!, config.params); + config.params = undefined; + } + break; + } + + case 'POST': { + if (headers?.['Content-Type'] === REQUEST_CONTENT_TYPE.FORM_URL) { + config.data = stringify(data); + } + break; + } + } + + return config; +} + +interface ResponseDataType { + data: { [key: string]: unknown }; + code: RequestCodeEnum; + message: string; +} +async function dealResponse(response: AxiosResponse) { + const { data } = response; + const { code, message } = data; + + switch (code) { + case REQUEST_CODE.SUCCESS: { + return data; + } + + default: { + errorAlert(message); + return Promise.reject(data); + } + } +} + +function dealRejected(err: Error) { + errorAlert(err.message); + return Promise.reject(err); +} + +export function getUrlWithQuery(url: string, params?: any) { + if (params && !isEmpty(params)) { + const querySymbol = isQuery(url) ? '&' : '?'; + + url = url + querySymbol + stringify(params); + } + + return url; +} + +export function generateFormUrl(data: object, lastKey = ''): string { + let str = ''; + const list = Object.entries(data); + + if (list.length) { + list.forEach(([key, value]) => { + const keyStr = lastKey ? lastKey + encodeURI('[' + key + ']') : encodeURI(key); + + if (isObject(value)) { + str += generateFormUrl(value, keyStr); + } else { + const valStr = isNil(value) ? '' : encodeURIComponent(value); + str += `&${keyStr}=${valStr}`; + } + }); + + return lastKey ? str : str.substring(1); + } else { + return lastKey ? `&${lastKey}=` : ''; + } +} + +export default service; diff --git a/src/utils/tools.ts b/src/utils/tools.ts new file mode 100644 index 0000000..d74392b --- /dev/null +++ b/src/utils/tools.ts @@ -0,0 +1,31 @@ +import jsPDF from 'jspdf'; +import html2canvas from 'html2canvas'; + +export async function generatePDFAndUpload(elementId: string) { + const element = document.getElementById(elementId); + + if (!element) throw new Error('元素不存在'); + element.style.display = 'block'; + document.body.style.overflow = 'hidden'; + const canvas = await html2canvas(element); + element.style.display = 'none'; + document.body.style.overflow = 'auto'; + const imgData = canvas.toDataURL('image/png'); + const pdf = new jsPDF({ + unit: 'px', + format: [canvas.width, canvas.height], + orientation: 'p', + }); + + // 添加图片到PDF + pdf.addImage(imgData, 'JPEG', 0, 0, canvas.width, canvas.height, void 0, 'FAST'); + + // 将PDF转换为Blob对象 + const pdfBlob = await pdf.output('blob'); + const file = new File([pdfBlob], '123.pdf', { type: 'application/pdf' }); + + const test = URL.createObjectURL(file); + console.log(test, file); + + return file; +} diff --git a/src/utils/url.ts b/src/utils/url.ts new file mode 100644 index 0000000..a8464c3 --- /dev/null +++ b/src/utils/url.ts @@ -0,0 +1,12 @@ +import { isEmpty } from 'lodash-es'; +import { stringify } from 'qs'; + +export function replaceState(replaceQuery = {}, url = '', stateObj = window.history.state, title = '') { + let address = url || window.location.pathname; + + if (!isEmpty(replaceQuery)) { + address += `?${stringify(replaceQuery)}`; + } + + window.history.replaceState(stateObj, title, address); +} diff --git a/src/utils/validate.ts b/src/utils/validate.ts new file mode 100644 index 0000000..d13f7b2 --- /dev/null +++ b/src/utils/validate.ts @@ -0,0 +1,51 @@ +export const isDateRegExp = /[12]\d{3}[-/]((0[1-9])|(1[0-2]))[-/]((0[1-9])|([12][0-9])|(3[0-1]))/; +export const isQueryRegExp = /\/.*\?.*=/; +export const isMobileRegExp = /^1[3456789]\d{9}$/; +export const is1688UrlRegExp = /(.*\.1688\.com\/)/; +export const isExternalRegExp = /^(http(s)?|mailto|tel|\/\/)/; +export const matchMoneyRegExp = /(0(\.[\d]{0,2})?)|([1-9]{1}[\d]*(\.)?[\d]{0,2})/gi; +export const isTelePhoneRegExp = /^(\+\d{2}-)?0\d{2,3}-?\d{7,8}$/; +export const isFixedPhoneRegExp = /^(\d{3}-\d{7,8}|\d{4}-\d{7,8})$/; +export const isVirtualPhoneRegExp = /^1[3456789]\d{9}-(\d{4})?$/; +export const is400TelePhoneRegExp = /^(\+86-)?400(-?\d{3,4}){2,3}$/; +export const isRelativeRootRegExp = /^\/[^/]+/; + +export function isDate(str: string) { + return isDateRegExp.test(str); +} + +export function isQuery(str: string) { + return isQueryRegExp.test(str); +} + +export function isMobile(str: string) { + return isMobileRegExp.test(str); +} + +export function is1688Url(str: string) { + return is1688UrlRegExp.test(str); +} + +export function isExternal(str: string) { + return isExternalRegExp.test(str); +} + +export function isTelePhone(str: string) { + return isTelePhoneRegExp.test(str); +} + +export function isFixedPhone(str: string) { + return isFixedPhoneRegExp.test(str); +} + +export function isVirtualPhone(str: string) { + return isVirtualPhoneRegExp.test(str); +} + +export function is400Phone(str: string) { + return is400TelePhoneRegExp.test(str); +} + +export function isRelativeRoot(str: string) { + return isRelativeRootRegExp.test(str); +} diff --git a/src/views/404/index.vue b/src/views/404/index.vue new file mode 100644 index 0000000..07c4118 --- /dev/null +++ b/src/views/404/index.vue @@ -0,0 +1,14 @@ + + + + + diff --git a/src/views/callback/index.vue b/src/views/callback/index.vue new file mode 100644 index 0000000..ee64084 --- /dev/null +++ b/src/views/callback/index.vue @@ -0,0 +1,343 @@ + + + + + diff --git a/src/views/sign/index.vue b/src/views/sign/index.vue new file mode 100644 index 0000000..34c278f --- /dev/null +++ b/src/views/sign/index.vue @@ -0,0 +1,259 @@ + + + + + diff --git a/src/views/tender/components/CustomerNotificationDialog/index.vue b/src/views/tender/components/CustomerNotificationDialog/index.vue new file mode 100644 index 0000000..f415361 --- /dev/null +++ b/src/views/tender/components/CustomerNotificationDialog/index.vue @@ -0,0 +1,120 @@ + + + + + + + diff --git a/src/views/tender/components/CustomerNotificationDialog2/index.vue b/src/views/tender/components/CustomerNotificationDialog2/index.vue new file mode 100644 index 0000000..0bd1018 --- /dev/null +++ b/src/views/tender/components/CustomerNotificationDialog2/index.vue @@ -0,0 +1,110 @@ + + + + + + + diff --git a/src/views/tender/components/ModifyDialog/index.vue b/src/views/tender/components/ModifyDialog/index.vue new file mode 100644 index 0000000..50e4b50 --- /dev/null +++ b/src/views/tender/components/ModifyDialog/index.vue @@ -0,0 +1,221 @@ + + + + + + + diff --git a/src/views/tender/components/ModifyInvoiceDialog/index.vue b/src/views/tender/components/ModifyInvoiceDialog/index.vue new file mode 100644 index 0000000..ffd78e0 --- /dev/null +++ b/src/views/tender/components/ModifyInvoiceDialog/index.vue @@ -0,0 +1,188 @@ + + + + + + + diff --git a/src/views/tender/components/PdfBox/index.vue b/src/views/tender/components/PdfBox/index.vue new file mode 100644 index 0000000..b895115 --- /dev/null +++ b/src/views/tender/components/PdfBox/index.vue @@ -0,0 +1,776 @@ + + + diff --git a/src/views/tender/components/index.ts b/src/views/tender/components/index.ts new file mode 100644 index 0000000..b9e574b --- /dev/null +++ b/src/views/tender/components/index.ts @@ -0,0 +1,5 @@ +export { default as PdfBox } from './PdfBox/index.vue'; +export { default as ModifyDialog } from './ModifyDialog/index.vue'; +export { default as ModifyInvoiceDialog } from './ModifyInvoiceDialog/index.vue'; +export { default as CustomerNotificationDialog } from './CustomerNotificationDialog/index.vue'; +export { default as CustomerNotificationDialog2 } from './CustomerNotificationDialog2/index.vue'; diff --git a/src/views/tender/index.vue b/src/views/tender/index.vue new file mode 100644 index 0000000..b51b4a1 --- /dev/null +++ b/src/views/tender/index.vue @@ -0,0 +1,553 @@ + + + + + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e488e04 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "target": "esnext", + "module": "esnext", + "strict": true, + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true, + "types": ["node", "element-plus/global", "vite/client"], + "jsx": "preserve", + "allowJs": true, + "paths": { + "@/*": ["./src/*"] + }, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true + }, + "include": ["src/**/*.vue", "src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], + "exclude": ["node_modules"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..173768e --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,29 @@ +// good +import vue from '@vitejs/plugin-vue'; +import { resolve } from 'path'; +import { createHtmlPlugin } from 'vite-plugin-html'; + +import { REQUEST_BASE_URL } from './src/constant/request'; + +import type { UserConfigExport } from 'vite'; + +export default () => { + const target = 'http://fjtb.bj-eib.com/api'; + const baseConfig: UserConfigExport = { + server: { + port: 80, + open: true, + proxy: { + [REQUEST_BASE_URL]: { + target, + changeOrigin: true, + rewrite: path => path.replace(REQUEST_BASE_URL, ''), + }, + }, + }, + resolve: { alias: { '@': resolve(process.cwd(), './src') } }, + plugins: [vue(), createHtmlPlugin({ entry: '/src/main.ts', minify: true })], + }; + + return baseConfig; +};