This commit is contained in:
xsl
2026-01-03 13:07:34 +08:00
commit a68e554ab1
31 changed files with 16129 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
node_modules
+53
View File
@@ -0,0 +1,53 @@
module.exports = {
env: {
browser: true,
es2021: true,
'vue/setup-compiler-macros': true
},
extends: [
'plugin:vue/essential',
'airbnb-base',
'plugin:prettier/recommended',
'plugin:import/recommended'
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: ['vue', '@typescript-eslint'],
overrides: [
{
files: ['*.vue'],
rules: {
indent: 'off'
}
}
],
settings: {
'import/resolver': {
alias: {
map: [['@components', './src/components']]
}
}
},
rules: {
'vue/no-multiple-template-root': 0,
'vue/script-indent': ['error', 2, { baseIndent: 1 }],
'no-console': 0,
'no-plusplus': 0,
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: ['**/*.test.ts', '**/*.test.js', 'vite.config.ts']
}
],
'vue/multi-word-component-names': 0,
'no-underscore-dangle': 0
}
}
+24
View File
@@ -0,0 +1,24 @@
# 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
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
helper.json
+10
View File
@@ -0,0 +1,10 @@
{
"useTabs": false,
"tabWidth": 2,
"printWidth": 100,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"semi": false,
"vueIndentScriptAndStyle": true
}
+7
View File
@@ -0,0 +1,7 @@
# 说明
由于项目要的急,就随手用了以前的脚手架去初始化的项目,是我几年前vue3刚出来没多久的时候弄的,没有升级
一些依赖版本都比较老,自动提示也不是很流畅
幸亏,文件比较少,直接把页面文件拷走就能用
+8
View File
@@ -0,0 +1,8 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-auto-import
export {}
declare global {
}
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional']
}
+12
View File
@@ -0,0 +1,12 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
declare module '@vue/runtime-core' {
export interface GlobalComponents {
Login: typeof import('./src/components/Login.vue')['default']
}
}
export {}
+25
View File
@@ -0,0 +1,25 @@
import { NodeSSH } from 'node-ssh'
// eslint-disable-next-line no-undef
console.log(process.env.PASSWORD)
const main = async () => {
const ssh = new NodeSSH()
await ssh.connect({
host: '47.99.188.89',
username: 'root',
password: 'Szlc123456'
})
console.log('上传中...')
// eslint-disable-next-line no-undef
await ssh.putDirectory('dist', '/home/gjf/digital_login/h5')
console.log('上传成功')
// eslint-disable-next-line no-undef
globalThis.process.exit(0)
}
main()
+13
View File
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>数字力场官网</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+10368
View File
File diff suppressed because it is too large Load Diff
+55
View File
@@ -0,0 +1,55 @@
{
"name": "vue_ts",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite --force",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"prepare": "husky install",
"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx,.vue",
"commit": "commit",
"bp": "pnpm build && node deploy.mjs"
},
"lint-staged": {
"**/*.{js,jsx,tsx,ts,less,md,json,vue}": [
"prettier --write"
]
},
"dependencies": {
"axios": "^1.7.2",
"element-plus": "^2.7.5",
"node-ssh": "^13.2.0",
"sass": "^1.77.5",
"unplugin-auto-import": "0.16.1",
"unplugin-vue-components": "0.20.1",
"vue": "^3.2.25"
},
"devDependencies": {
"@commitlint/cli": "^16.2.1",
"@commitlint/config-angular": "^16.2.1",
"@commitlint/config-conventional": "^16.2.1",
"@commitlint/format": "^16.2.1",
"@commitlint/prompt-cli": "^16.2.1",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"@vitejs/plugin-vue": "^2.2.0",
"conventional-changelog-atom": "^2.0.8",
"eslint": "^8.10.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.5.0",
"husky": "^7.0.4",
"less": "^4.1.2",
"lint-staged": "^12.3.5",
"prettier": "^2.5.1",
"typescript": "^4.5.4",
"vite": "^2.8.0",
"vite-plugin-eslint": "^1.3.0",
"vue-tsc": "^0.29.8"
}
}
+5081
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+20
View File
@@ -0,0 +1,20 @@
<script setup lang="ts">
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import Login from '@components/Login.vue'
</script>
<template>
<Login />
</template>
<style>
#app {
/* font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px; */
}
</style>
+24
View File
@@ -0,0 +1,24 @@
import axios from 'axios'
const instance = axios.create({
// base接口,表示请求URL的公共部分
baseURL: '',
// 超时 设置为5分钟
timeout: 5 * 60 * 1000
})
instance.interceptors.response.use(
(res) => res.data,
(error) => {
console.log(error)
}
)
export const sms = (data = {}) =>
instance({
url: '/api/digital/sms',
method: 'post',
data
})
export default { sms }
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+342
View File
@@ -0,0 +1,342 @@
<template>
<div class="login">
<div class="mask">
<div class="login_box">
<template v-if="info.logo">
<img :src="info.logo" alt="" class="logo" />
<span>{{ info.title }}</span>
</template>
<div class="phone_box">
<div class="a_">+86</div>
<div class="xian"></div>
<input class="inp" placeholder="请输入手机号码" maxlength="11" v-model="obj.phone" />
</div>
<div class="msg_box">
<input class="inp" placeholder="请输入验证码" :maxlength="6" v-model="obj.captcha" />
<div class="xian"></div>
<div class="msg_btn" v-if="!timeout" @click="getSms">{{ obj.codeText }}</div>
<div class="msg_btn" v-else>{{ timeout }}s</div>
</div>
<div class="yingshi">
<div class="ckh"></div>
<div :style="{ color: '#C4C4C4' }">已同意 用户条款 隐私政策</div>
</div>
<div class="btn" @click="login">登录</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import axios from 'axios'
import { onBeforeMount, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
// import logo from '../assets/static/shuzilichang.png'
import mainLogoImg from '../assets/static/shuzilichang.png'
import jfLogoImg from '../assets/static/jf_logo.png'
import juyunLogoImg from '../assets/static/Juyun.png'
const { host } = window.location
type Info = {
title: string
logo: string
}
const globalInfo = reactive<Record<'jf' | 'main' | 'fashionroom', Info>>({
jf: {
title: '精分数据',
logo: jfLogoImg
},
fashionroom: {
title: '聚云科技',
logo: juyunLogoImg
},
main: {
title: '',
logo: mainLogoImg
}
})
const info = ref<Info>({
title: '',
logo: mainLogoImg
})
// const logoImgRef = computed(() => (host.includes('jf') ? jfLogoImg : mainLogoImg))
onBeforeMount(() => {
const { referrer } = document
if (host.includes('jf')) {
info.value = globalInfo.jf
}
console.log('AT-[ referrer &&&&&********** ]', referrer)
if (referrer.includes('fashionroom')) {
info.value = globalInfo.fashionroom
}
document.title = info.value?.title || '数字力场官网'
})
const instance = axios.create({
// base接口,表示请求URL的公共部分
baseURL: '',
// 超时 设置为5分钟
timeout: 5 * 60 * 1000
})
instance.interceptors.response.use(
(res) => res.data,
(error) => {
console.log(error)
}
)
const obj = reactive<{
phone: string | undefined
codeText: string
captcha: number | undefined
}>({
phone: undefined,
codeText: '验证码',
captcha: undefined
})
const timeout = ref(0)
const sms = (data = {}) =>
instance<any, any>({
url: '/api/digital/sms',
method: 'post',
data
})
const phoneLogin = (data = {}) =>
instance<any, any>({
url: '/api/digital/phoneLogin',
method: 'post',
data
})
const reg = /^1[345789]\d{9}$/
const login = async () => {
console.log(obj)
const { phone, captcha } = obj
if (!phone || !reg.test(phone) || String(captcha).length !== 6) {
ElMessage({
message: '请输入正确的手机号和验证码',
type: 'warning'
})
return
}
const res = await phoneLogin({ phone, captcha })
if (res.code !== 200) {
ElMessage({
message: res.message,
type: 'error'
})
} else {
ElMessage({
message: '登录成功',
type: 'success'
})
document.cookie = `token=${res.data.token};domain=aidigitalfield.com`
if (document.referrer.includes('fashionroom')) {
console.log('命中')
window.location.href = `${document.referrer}?key=${res.data.token}`
} else {
window.location.href = document.referrer
}
}
}
const run = (num: number) => {
timeout.value = num
if (timeout.value) {
setTimeout(() => {
run(timeout.value - 1)
}, 1000)
}
}
const getSms = async () => {
const { phone } = obj
if (!phone || !reg.test(phone)) {
ElMessage({ message: '请输入11位手机号', type: 'warning' })
return
}
const res = await sms({ phone })
if (res.code === 200) {
ElMessage({ message: '发送成功', type: 'success' })
run(60)
} else {
ElMessage({ message: res.message, type: 'error' })
}
}
</script>
<style lang="scss">
* {
margin: 0;
padding: 0;
}
.login {
background: url('../assets/static/background.jpg') no-repeat center;
background-size: 100% auto;
width: 100vw;
height: 100vh;
.mask {
background-color: rgba(0, 0, 0, 0.8);
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.login_box {
width: 320px;
height: 250px;
margin-left: 27px;
background-color: #fff;
padding: 17px 20px;
box-sizing: border-box;
text-align: center;
margin: 0 auto;
input {
border: none;
outline: none;
}
.logo {
margin: 0 auto;
display: inline-block;
height: 31px;
vertical-align: middle;
}
.phone_box {
width: 280px;
height: 40px;
padding: 10px 16px;
box-sizing: border-box;
border: 1px solid #000000;
display: flex;
align-items: center;
margin-top: 10px;
.a_ {
font-size: 14px;
color: #4d505d;
}
.xian {
width: 1px;
height: 19px;
border-right: #c4c4c4 solid 1px;
margin-left: 8px;
}
.inp {
margin-left: 8px;
font-family: PingFang SC;
font-size: 14px;
color: #4d505d;
}
}
.msg_box {
width: 280px;
height: 40px;
padding: 10px 16px;
box-sizing: border-box;
border: 1px solid #000000;
display: flex;
align-items: center;
margin-top: 6px;
.xian {
width: 1px;
height: 14px;
border-right: #c4c4c4 solid 1px;
margin-left: 8px;
}
.inp {
font-family: PingFang SC;
font-size: 14px;
color: #4d505d;
flex: 1;
}
.msg_btn {
width: 59px;
font-family: PingFang SC;
font-size: 14px;
text-align: center;
color: #4d505d;
font-weight: 700;
cursor: pointer;
}
}
.yingshi {
margin: 0 auto;
display: flex;
align-items: center;
font-family: PingFang SC;
font-size: 12px;
font-weight: 700;
color: #c4c4c4;
margin-top: 10px;
display: flex;
.ckh {
width: 15px;
height: 15px;
background: #d9d9d9;
border: 1px solid #000000;
margin-right: 8px;
margin-left: 16px;
text-align: center;
color: #4d505d;
}
}
.btn {
width: 112px;
height: 40px;
border-radius: 4px;
background: #000000;
font-family: Epilogue;
font-size: 14px;
font-weight: 700;
line-height: 40px;
text-align: center;
color: #fcfcfc;
margin: 0 auto;
margin-top: 16px;
cursor: pointer;
}
}
}
}
</style>
+8
View File
@@ -0,0 +1,8 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}
+11
View File
@@ -0,0 +1,11 @@
import { createApp } from 'vue'
// import ElementPlus from 'element-plus'
import { ElMessage } from 'element-plus'
import App from './App.vue'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(ElMessage)
app.mount('#app')
// app.use(ElementPlus, { size: 'small', zIndex: 3000 })
+17
View File
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"skipLibCheck": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
+8
View File
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"composite": true,
"module": "esnext",
"moduleResolution": "node"
},
"include": ["vite.config.ts"]
}
+39
View File
@@ -0,0 +1,39 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
eslintPlugin(),
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
resolve: {
alias: {
'@components': '/src/components',
'@': '/src/'
}
},
server: {
cors: true,
proxy: {
'/api': {
target: 'https://vhost.aidigitalfield.com',
changeOrigin: true
}
},
port: 7766
}
})