commit 2ec98c0b90ac3d558b7476b45345a5e76f18ea3c Author: Hx <2294602187@qq.com> Date: Thu Mar 27 10:14:38 2025 +0800 init diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..46ac588 --- /dev/null +++ b/.env.development @@ -0,0 +1,5 @@ +ENV='development' +# base api +VITE_APP_BASE_URL = 'http://pos-api.lingji.vip' +VITE_APP_BASE_PRE = '/shenname' +VITE_APP_BASE_NAME = 'POS' diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..6ca60a8 --- /dev/null +++ b/.env.production @@ -0,0 +1,6 @@ +ENV='production' +# base api +VITE_APP_BASE_URL = 'http://pos-api.lingji.vip' +VITE_APP_BASE_PRE = 'http://pos-api.lingji.vip' +VITE_APP_BASE_NAME = 'POS' + diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..0ea3957 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +dist +node_modules +uni_modules diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..f44624e --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,146 @@ +// @see https://eslint.bootcss.com/docs/rules/ + +module.exports = { + env: { + browser: true, + es2021: true, + node: true + }, + globals: { + NodeJS: 'readonly' + }, + /* 指定如何解析语法 */ + parser: 'vue-eslint-parser', + /** 优先级低于 parse 的语法解析配置 */ + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + parser: '@typescript-eslint/parser', + jsxPragma: 'React', + ecmaFeatures: { + jsx: true + } + }, + /* 继承已有的规则 */ + extends: ['eslint:recommended', 'plugin:vue/vue3-essential', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'], + plugins: ['vue', '@typescript-eslint'], + overrides: [ + { + files: ['*.ts', '*.tsx', '*.vue'], + rules: { + 'no-undef': 0 + } + } + ], + /* + * 'off' 或 0 ==> 关闭规则 + * 'warn' 或 1 ==> 打开的规则作为警告(不影响代码执行) + * 'error' 或 2 ==> 规则作为一个错误(代码不能执行,界面报错) + */ + rules: { + // typeScript (https://typescript-eslint.io/rules) + '@typescript-eslint/no-unused-vars': [2, { argsIgnorePattern: '^_' }], // 禁止定义未使用的变量 + '@typescript-eslint/prefer-ts-expect-error': 2, // 禁止使用 @ts-ignore + '@typescript-eslint/no-explicit-any': 0, // 禁止使用 any 类型 + '@typescript-eslint/no-non-null-assertion': 0, + '@typescript-eslint/no-namespace': 0, // 禁止使用自定义 TypeScript 模块和命名空间。 + '@typescript-eslint/semi': 0, + 'no-prototype-builtins': 0, // 可以使用obj.hasOwnProperty() + '@typescript-eslint/no-var-requires': 0, // 不允许在import 中使用require + '@typescript-eslint/no-empty-function': 2, // 关闭空方法检查 + // eslint-plugin-vue (https://eslint.vuejs.org/rules/) + 'vue/multi-word-component-names': 0, // 要求组件名称始终为 “-” 链接的单词 + 'vue/script-setup-uses-vars': 2, // 防止 + +`; + createStream.write(template); + createStream.end(); + console.log('\x1B[34m', `pages ${name} created successfully.`); + } + console.log('\x1B[32m%s\x1B[39m', '\n All files are created successfully.\n'); +} + +addPages(newPages); \ No newline at end of file diff --git a/auto/preinstall.js b/auto/preinstall.js new file mode 100644 index 0000000..01f63a5 --- /dev/null +++ b/auto/preinstall.js @@ -0,0 +1,4 @@ +if (!/pnpm/.test(process.env.npm_execpath || '')) { + console.warn(`\u001b[33mThis repository must using pnpm as the package manager ` + ` for scripts to work properly.\u001b[39m\n`) + process.exit(1) +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..b05e747 --- /dev/null +++ b/index.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..350e978 --- /dev/null +++ b/package.json @@ -0,0 +1,100 @@ +{ + "name": "uni-preset-vue", + "version": "0.0.0", + "scripts": { + "dev:app": "uni -p app", + "dev:app-android": "uni -p app-android", + "dev:app-ios": "uni -p app-ios", + "dev:custom": "uni -p", + "dev:h5": "uni", + "dev:h5:prop": "uni --mode=production", + "dev:h5:ssr": "uni --ssr", + "dev:mp-alipay": "uni -p mp-alipay", + "dev:mp-baidu": "uni -p mp-baidu", + "dev:mp-jd": "uni -p mp-jd", + "dev:mp-kuaishou": "uni -p mp-kuaishou", + "dev:mp-lark": "uni -p mp-lark", + "dev:mp-qq": "uni -p mp-qq", + "dev:mp-toutiao": "uni -p mp-toutiao", + "dev:mp-weixin": "uni -p mp-weixin", + "dev:quickapp-webview": "uni -p quickapp-webview", + "dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei", + "dev:quickapp-webview-union": "uni -p quickapp-webview-union", + "build:app": "uni build -p app", + "build:app-android": "uni build -p app-android", + "build:app-ios": "uni build -p app-ios", + "build:custom": "uni build -p", + "build:h5": "uni build", + "build:h5:ssr": "uni build --ssr", + "build:mp-alipay": "uni build -p mp-alipay", + "build:mp-baidu": "uni build -p mp-baidu", + "build:mp-jd": "uni build -p mp-jd", + "build:mp-kuaishou": "uni build -p mp-kuaishou", + "build:mp-lark": "uni build -p mp-lark", + "build:mp-qq": "uni build -p mp-qq", + "build:mp-toutiao": "uni build -p mp-toutiao", + "build:mp-weixin": "uni build -p mp-weixin", + "build:quickapp-webview": "uni build -p quickapp-webview", + "build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei", + "build:quickapp-webview-union": "uni build -p quickapp-webview-union", + "type-check": "vue-tsc --noEmit", + "add": "node ./auto/addPage.ts", + "preinstall": "node ./auto/preinstall.js", + "lint": "eslint --ext .ts,.js,.vue ./src", + "fix": "eslint --fix --ext .ts,.js,.vue ./src", + "prepare": "husky install", + "rm": "rm -rf node_modules package-lock.json pnpm-lock.yaml && pnpm install" + }, + "dependencies": { + "@dcloudio/uni-app": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-app-plus": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-components": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-h5": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-alipay": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-baidu": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-jd": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-lark": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-qq": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-weixin": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-mp-xhs": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3081220230802001", + "@qiun/ucharts": "2.5.0-20230101", + "animate.css": "^4.1.1", + "echarts": "^5.5.0", + "pinia": "2.0.36", + "sass": "^1.63.2", + "uview-plus": "^3.4.9", + "vue": "^3.2.45", + "vue-i18n": "^9.1.9" + }, + "devDependencies": { + "@babel/eslint-parser": "^7.22.9", + "@dcloudio/types": "^3.3.2", + "@dcloudio/uni-automator": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-cli-shared": "3.0.0-alpha-3081220230802001", + "@dcloudio/uni-stacktracey": "3.0.0-alpha-3081220230802001", + "@dcloudio/vite-plugin-uni": "3.0.0-alpha-3081220230802001", + "@typescript-eslint/eslint-plugin": "^6.2.1", + "@typescript-eslint/parser": "^6.2.1", + "@vue/tsconfig": "^0.1.3", + "@vueuse/core": "^10.3.0", + "eslint": "^8.46.0", + "eslint-config-prettier": "^8.9.0", + "eslint-plugin-import": "^2.28.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-vue": "^9.16.1", + "feng-uniapp-exploit": "^1.0.2", + "husky": "^8.0.0", + "pinia-plugin-unistorage": "^0.0.17", + "prettier": "^3.0.0", + "sass-loader": "^10.4.1", + "typescript": "^4.9.4", + "unplugin-auto-import": "^0.16.6", + "unplugin-vue-components": "^0.25.1", + "vite": "4.0.3", + "vue-tsc": "^1.0.24" + } +} \ No newline at end of file diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..b95142e --- /dev/null +++ b/src/App.vue @@ -0,0 +1,29 @@ + + + + diff --git a/src/api/common.ts b/src/api/common.ts new file mode 100644 index 0000000..793bc64 --- /dev/null +++ b/src/api/common.ts @@ -0,0 +1,98 @@ +import { request } from '@/utils/http' + +export interface sendCodeType { + phone: number | string +} + +export function sendCode(data: sendCodeType) { + return request.http({ + url: '/api/t.sms/sendCode', + data + }) +} + +// 上传图片 +export function uploadFile(file: any) { + let url = '' + // #ifdef APP-PLUS + url = import.meta.env.VITE_APP_BASE_URL + // #endif + // #ifdef H5 + url = import.meta.env.VITE_APP_BASE_PRE + // #endif + return new Promise((resolve, reject) => { + uni.uploadFile({ + url: `${url}/api/resources/upload`, + filePath: file, + name: 'file', + success: (res) => { + resolve(JSON.parse(res.data)) + }, + fail: (res) => { + reject(res) + } + }) + }) +} + +// 根据 KEY 获取对应数据 +export function getKeyData(key: string) { + return request.http({ + url: '/api/t.systemData/getCategoryByKey', + data: { key: key } + }) +} + +// 根据 KEY 获取对应系统设置 +export function getKeySetting(key: string) { + return request.http({ + url: '/api/t.systemData/getSettingByKey', + data: { key: key } + }) +} + +// 获取无限极分类数据 +export function getCategoryData() { + return request.http({ + url: '/api/t.systemData/categoryTree' + }) +} + +// 意见反馈 +export interface feedbackType { + type: useType + category_id: number + content: string + image?: string + contact_information: string +} + +export function feedback(data: feedbackType) { + return request.http({ + url: '/api/t.feedback/add', + data + }) +} + +// 购买支付接口 +export function pay(data: { policy_id: number; uid: number; pay_amount: number; version: string }) { + return request.http({ + url: '/api/t.notify/buyAgentPolicyNotify', + data + }) +} + +// 直采列表 +export function voucherQuery() { + return request.http({ + url: '/api/d.pickGiftBag/query' + }) +} + +// 直采支付 +export function voucherPay(data: { id: number }) { + return request.http({ + url: '/api/d.pickGiftBag/buy', + data + }) +} diff --git a/src/components/ex-list/ex-list.vue b/src/components/ex-list/ex-list.vue new file mode 100644 index 0000000..8d86195 --- /dev/null +++ b/src/components/ex-list/ex-list.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/src/components/ex-tags/ex-tags.vue b/src/components/ex-tags/ex-tags.vue new file mode 100644 index 0000000..119e414 --- /dev/null +++ b/src/components/ex-tags/ex-tags.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/config/index.ts b/src/config/index.ts new file mode 100644 index 0000000..31f99ca --- /dev/null +++ b/src/config/index.ts @@ -0,0 +1,13 @@ +export const Prefix = 'POS_' + +export const getPrefixName = (name: string) => { + return Prefix + name +} + +export function getAuthorization() { + return uni.getStorageSync(getPrefixName('user')) +} + +export function removeAuthorization() { + return uni.removeStorageSync(getPrefixName('user')) +} diff --git a/src/hooks/paginationLoader.ts b/src/hooks/paginationLoader.ts new file mode 100644 index 0000000..bc29f5e --- /dev/null +++ b/src/hooks/paginationLoader.ts @@ -0,0 +1,128 @@ +/* + * @description: 分页请求 + * @fileName: useListLoadClass.ts + * @author: lxx + * @date: 2023-07-08 08:55:52 + * @version: V1.0.0 + */ +import { ref } from 'vue' + +class PaginationLoader { + // 分页数据 + private data = ref([]) + + // 分页基础参数 + private requestParams = { + page: 1, + limit: 10 + } + + // 是否正在加载 + private isLoading = ref(false) + + // 是否还有更多数据 + private hasMore = ref(true) + + // 请求函数(由外部传入) + private fetchFn: (formData: Object, onSuccess: Function) => Function + + constructor(fetchFn: (formData: Object, onSuccess: Function) => Function) { + this.fetchFn = fetchFn + } + + // 获取当前数据 + get dataList() { + return this.data.value + } + + // 获取是否正在加载 + get loading() { + return this.isLoading.value + } + + // 获取是否还有更多数据 + get more() { + return this.hasMore.value + } + + // 加载下一页数据 + async loadNextPage() { + // if (this.isLoading.value || !this.hasMore.value) return + + // uni.showLoading({ title: '加载中...' }) + + // this.isLoading.value = true + + // try { + // const result = await this.fetchFn(this.currentPage.value, this.pageSize) + + // if (result.length > 0) { + // this.data.value = [...this.data.value, ...result] + // this.currentPage.value += 1 + // } else { + // this.hasMore.value = false // 没有更多数据 + // } + // } catch (error) { + // console.error('加载数据失败:', error) + // } finally { + // this.isLoading.value = false + // } + uni.showLoading({ title: '数据加载中' }) + this.isLoading.value = false + const params = { ...this.requestParams } as { [n: string]: string | number | boolean } + + setTimeout(() => { + this.fetchFn(params, ({ data }: { data: { data: any; total: number } }) => { + this.isLoading.value = true + this.requestParams.page = params.page as number + this.requestParams.limit = params.limit as number + this.data.value = [...this.data.value, ...data.data] + uni.hideLoading() + }) + }, 100) + } + + // 重置分页状态 + reset() { + this.data.value = [] + this.requestParams.page = 1 + this.hasMore.value = true + this.isLoading.value = false + } +} + +// export default PaginationLoader + +const fetchData = async (formData: any, onSuccess: Function) => { + const submitData = { ...formData } + point_order_list(submitData).then((res) => { + const { data } = res as { data: { data: any; total: number } } + onSuccess({ data }) + }) + // // 模拟接口请求 + // return new Promise<{ id: number; name: string }[]>((resolve) => { + // setTimeout(() => { + // const data = Array.from({ length: pageSize }, (_, index) => ({ + // id: (page - 1) * pageSize + index, + // name: `Item ${(page - 1) * pageSize + index}` + // })) + // resolve(data) + // }, 1000) + // }) +} + +// 创建分页加载实例 +const paginationLoader = new PaginationLoader(fetchData) + +// 加载下一页数据 +paginationLoader.loadNextPage(formDate.value) + +// 初始化加载第一页数据 +paginationLoader.loadNextPage() + +return { + dataList: paginationLoader.dataList, + loading: paginationLoader.loading, + more: paginationLoader.more, + loadNextPage +} diff --git a/src/hooks/useListLoadClass.ts b/src/hooks/useListLoadClass.ts new file mode 100644 index 0000000..8027773 --- /dev/null +++ b/src/hooks/useListLoadClass.ts @@ -0,0 +1,125 @@ +/* + * @description: 分页请求 + * @fileName: useListLoadClass.ts + * @author: lxx + * @date: 2023-07-08 08:55:52 + * @version: V1.0.0 + */ +import { ref, computed } from 'vue' +import { onReachBottom } from '@dcloudio/uni-app' + +class LoadDataClass { + // 请求参数 + static queryParams = { + page: 1, + limit: 10 + } + // 列表数据 + list = ref([]) + total = ref(0) + // 前置处理方法 + afterLoadData: Function | undefined + // 请求方法 + Query: Function + // 加载状态参数 + isLoading = ref(false) + // 无更多数据了 + isNoData = computed(() => { + if (LoadDataClass.queryParams.page * LoadDataClass.queryParams.limit >= this.total.value) { + return true + } else { + return false + } + }) + // 显示暂无数据 + isEmpty = computed(() => { + if (this.total.value === 0) { + return true + } else { + return false + } + }) + + constructor(apiFunctions: Function, afterLoadData?: Function, options?: any) { + this.Query = apiFunctions + this.afterLoadData = afterLoadData + // 存在额外参数拼接 + if (options) { + LoadDataClass.queryParams = { ...LoadDataClass.queryParams, ...options } + } + // 加载数据 + this.LoadData() + } + // 加载数据 + LoadData = async () => { + uni.showLoading({ + title: '加载中...' + }) + this.isLoading.value = true + const res = await this.Query(LoadDataClass.queryParams) + this.afterLoadData && this.afterLoadData(res) + this.total.value = res.data.total + this.list.value = this.list.value.concat(res.data.data) + + uni.hideLoading() + uni.stopPullDownRefresh() + this.isLoading.value = false + } + // 加载更多 + LoadMore = () => { + if (this.isNoData.value || this.isLoading.value) return // 无数据或者加载中不进行加载 + LoadDataClass.queryParams.page += 1 + this.LoadData() + } + // 重置参数 + queryParamsReset = () => { + LoadDataClass.queryParams = { + page: 1, + limit: 10 + } + } + + /** + * 刷新 + * @param isClear: 是否清空数据 + */ + ReLoad = (isClear: boolean = true) => { + this.isLoading.value = false + this.list.value = [] + if (isClear) { + this.queryParamsReset() + } else { + LoadDataClass.queryParams.page = 1 + } + + this.LoadData() + } +} +/** + * 分页加载数据方法 + * @param api: ListAPI 方法 + * @param afterLoadData: res数据前置处理方法 + * @returns + */ +interface LoadDataInt { + api: Function + afterLoadData?: Function + options?: any +} + +export function LoadData({ api, afterLoadData, options }: LoadDataInt) { + const data = new LoadDataClass(api, afterLoadData, options) + + // 下拉加载 + onReachBottom(() => { + console.log('onReachBottom') + data.LoadMore() + }) + return { + list: data.list, + isLoading: data.isLoading, + isNoData: data.isNoData, + isEmpty: data.isEmpty, + ReLoad: data.ReLoad + } +} diff --git a/src/hooks/usePagingLoad.ts b/src/hooks/usePagingLoad.ts new file mode 100644 index 0000000..d66380f --- /dev/null +++ b/src/hooks/usePagingLoad.ts @@ -0,0 +1,127 @@ +import { ref, reactive, computed } from 'vue' +import { onReachBottom } from '@dcloudio/uni-app' +/* + * @description: 分页请求 + * @fileName: useListLoadClass.ts + * @author: lxx + * @date: 2023-07-08 08:55:52 + * @version: V1.0.0 + * loading状态 + * @param {*} Query 请求函数 + * @param {*} LoadData 加载数据方法 + * @param {*} ReLoad (isClear?: boolean) 刷新列表数据 isClear 传入true时将请求参数(queryParams)还原初始化状态 + */ + +export function usePagingLoad(Query: any) { + // 下拉加载 + onReachBottom(() => { + console.log('onReachBottom') + loadMore() + }) + + const isLoading = ref(false) + let queryParams = reactive({} as any) + + queryParams = { + page: 1, + limit: 10 + } + + const total = ref(0) + + const list = ref([]) + // 无更多数据了 + const isNoData = computed(() => { + if (queryParams.page * queryParams.limit >= total.value) { + return true + } else { + return false + } + }) + // 显示暂无数据 + const isEmpty = computed(() => { + if (total.value === 0) { + return true + } else { + return false + } + }) + + interface optionInt { + key: string + val: any + } + + const LoadData = async (afterLoadData?: any, option?: optionInt[]) => { + const obj: any = {} + console.log('option', option) + if (option && option?.length > 0) { + option?.map((item) => { + obj[item?.key] = item.val + }) + } + // , ...rest: any[] + // if (rest.length > 0) { + // rest.map((item) => { + // obj[item?.key] = item?.val; + // }); + // } + queryParams = reactive({ ...queryParams, ...obj }) + + uni.showLoading({ + title: '加载中...' + }) + isLoading.value = true + const res = await Query(queryParams) + total.value = res?.data?.total + + // 数据加载完成后 设置 after 钩子 + afterLoadData && afterLoadData(res.data) + console.log('res.data', res.data) + + list.value = list.value.concat(res?.data?.data) + uni.hideLoading() + uni.stopPullDownRefresh() + isLoading.value = false + } + + // const afterLoadData = (data: any) => { + // console.log(data); + // }; + + const ReLoad = (option?: optionInt[], isClear?: boolean) => { + isLoading.value = false + list.value = [] + if (isClear) { + queryParams = reactive({ + page: 1, + limit: 10 + }) + } else { + queryParams.page = 1 + } + const obj: any = {} + if (option && option?.length > 0) { + option?.map((item) => { + obj[item?.key] = item.val + }) + } + queryParams = reactive({ ...queryParams, ...obj }) + LoadData() + } + + const loadMore = () => { + if (isNoData.value || isLoading.value) return // 无数据或者加载中不进行加载 + queryParams.page += 1 + LoadData() + } + + return { + list, + LoadData, + ReLoad, + isNoData, + isEmpty, + isLoading + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..8d202a8 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,16 @@ +import { createSSRApp } from 'vue' +import App from './App.vue' + +import uviewPlus from 'uview-plus' +import fengUniappExploit from 'feng-uniapp-exploit' + +import store from './store' + +export function createApp() { + const app = createSSRApp(App) + app.use(uviewPlus) + app.use(fengUniappExploit) + app.use(store) + + return { app } +} diff --git a/src/manifest.json b/src/manifest.json new file mode 100644 index 0000000..80d5370 --- /dev/null +++ b/src/manifest.json @@ -0,0 +1,131 @@ +{ + "name" : "新未来", + "appid" : "__UNI__1AE1F37", + "description" : "v3+ts+uniapp模版", + "versionName" : "1.0.68", + "versionCode" : 168, + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + "compatible" : { + "ignoreVersion" : true + }, + /* 模块配置 */ + "modules" : { + "Barcode" : {}, + "Camera" : {}, + "VideoPlayer" : {}, + "Share" : {}, + "Geolocation" : {}, + "Maps" : {} + }, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "minSdkVersion" : 21 + }, + /* ios打包配置 */ + "ios" : { + "dSYMs" : false + }, + /* SDK配置 */ + "sdkConfigs" : { + "ad" : {}, + "share" : { + "weixin" : { + "appid" : "wxd448c878a54da98d", + "UniversalLinks" : "" + } + }, + "geolocation" : { + "amap" : { + "name" : "amap_18648278829CcsBXVUm1", + "__platform__" : [ "ios", "android" ], + "appkey_ios" : "435934cdfcc901e4872a70391d92cccd", + "appkey_android" : "435934cdfcc901e4872a70391d92cccd" + } + }, + "maps" : { + "amap" : { + "name" : "amap_18648278829CcsBXVUm1", + "appkey_ios" : "435934cdfcc901e4872a70391d92cccd", + "appkey_android" : "435934cdfcc901e4872a70391d92cccd" + } + } + }, + "icons" : { + "android" : { + "hdpi" : "src/static/logo.png", + "xhdpi" : "src/static/logo.png", + "xxhdpi" : "src/static/logo.png", + "xxxhdpi" : "src/static/logo.png" + } + }, + "splashscreen" : { + "iosStyle" : "common", + "androidStyle" : "default", + "android" : { + "hdpi" : "C:/Users/Lenovo/Desktop/480x762.9/res/drawable-xhdpi/480x762.9.png", + "xhdpi" : "C:/Users/Lenovo/Desktop/720x1242.9/res/drawable-xhdpi/720x1242.9.png", + "xxhdpi" : "C:/Users/Lenovo/Desktop/1080x1882.9/res/drawable-xhdpi/1080x1882.9.png" + }, + "ios" : { + "storyboard" : "C:/Users/Lenovo/Desktop/CustomStoryboard.zip" + } + } + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false, + "es6" : true, + "postcss" : false, + "minified" : true + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "3" +} diff --git a/src/pages.json b/src/pages.json new file mode 100644 index 0000000..c982b41 --- /dev/null +++ b/src/pages.json @@ -0,0 +1,111 @@ +{ + "easycom": { + "autoscan": true, + "custom": { + "^ex-(.*)": "feng-uniapp-exploit/components/ex-$1/ex-$1.vue", + "^u-(.*)": "uview-plus/components/u-$1/u-$1.vue" + } + }, + "pages": [ + { + "path": "pages/votingElection/index", + "style": { + "navigationBarTitleText": "投票选举", + "enablePullDownRefresh": true + } + }, + { + "path": "pages/electionList/index", + "style": { + "navigationBarTitleText": "选举列表", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/electionResults/index", + "style": { + "navigationBarTitleText": "选举结果", + "navigationBarTextStyle": "white", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/myElection/index", + "style": { + "navigationBarTitleText": "我的选举", + "navigationBarTextStyle": "white", + "enablePullDownRefresh": false + } + }, + { + "name": "links", + "path": "pages/index/links", + "style": { + "navigationBarTitleText": "外部链接", + "enablePullDownRefresh": false + } + }, + { + "name": "guide", + "path": "pages/index/guide", + "style": { + "navigationBarTitleText": "用户指南", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "name": "user", + "path": "pages/mine/index", + "style": { + "navigationBarTitleText": "个人信息", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "tabBar": { + "color": "#9CA3AF", + "selectedColor": "#2563EB", + "borderStyle": "white", + "backgroundColor": "#F9FAFB", + "list": [ + { + "pagePath": "pages/votingElection/index", + "iconPath": "static/tabbar/tpxj.png", + "selectedIconPath": "static/tabbar/tpxj-select.png", + "text": "投票选举" + }, + { + "pagePath": "pages/electionList/index", + "iconPath": "static/tabbar/xjlb.png", + "selectedIconPath": "static/tabbar/xjlb-select.png", + "text": "选举列表" + }, + { + "pagePath": "pages/electionResults/index", + "iconPath": "static/tabbar/xjjg.png", + "selectedIconPath": "static/tabbar/xjjg-select.png", + "text": "选举结果" + }, + { + "pagePath": "pages/myElection/index", + "iconPath": "static/tabbar/wdxj.png", + "selectedIconPath": "static/tabbar/wdxj-select.png", + "text": "我的选举" + }, + { + "pagePath": "pages/mine/index", + "iconPath": "static/tabbar/grxx.png", + "selectedIconPath": "static/tabbar/grxx-select.png", + "text": "个人信息" + } + ] + } +} \ No newline at end of file diff --git a/src/pages/electionList/index.vue b/src/pages/electionList/index.vue new file mode 100644 index 0000000..197b0e5 --- /dev/null +++ b/src/pages/electionList/index.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/src/pages/electionResults/index.vue b/src/pages/electionResults/index.vue new file mode 100644 index 0000000..243ce38 --- /dev/null +++ b/src/pages/electionResults/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/pages/index/guide.vue b/src/pages/index/guide.vue new file mode 100644 index 0000000..3a4351a --- /dev/null +++ b/src/pages/index/guide.vue @@ -0,0 +1,112 @@ + + + + diff --git a/src/pages/index/links.vue b/src/pages/index/links.vue new file mode 100644 index 0000000..cb3c718 --- /dev/null +++ b/src/pages/index/links.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/pages/mine/index.vue b/src/pages/mine/index.vue new file mode 100644 index 0000000..628e05c --- /dev/null +++ b/src/pages/mine/index.vue @@ -0,0 +1,314 @@ + + + + diff --git a/src/pages/myElection/index.vue b/src/pages/myElection/index.vue new file mode 100644 index 0000000..9fa6173 --- /dev/null +++ b/src/pages/myElection/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/pages/votingElection/index.vue b/src/pages/votingElection/index.vue new file mode 100644 index 0000000..085d275 --- /dev/null +++ b/src/pages/votingElection/index.vue @@ -0,0 +1,338 @@ + + + + + diff --git a/src/permission.ts b/src/permission.ts new file mode 100644 index 0000000..ec90164 --- /dev/null +++ b/src/permission.ts @@ -0,0 +1,51 @@ +// import { getAuthorization } from '@/config' + +// 白名单 +// const whiteList = ['/agentpages/index/index', '/agentpages/mine/index'] + +export default async function () { + const list = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'] + + // 用遍历的方式分别为,uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab这4个路由方法添加拦截器 + list.forEach((item) => { + uni.addInterceptor(item, { + invoke(e) { + console.log('e', e) + + // 获取要跳转的页面路径(url去掉"?"和"?"后的参数) + // const url = e.url.split('?')[0] + // const type = url.split('/')[1] || '' + + // let data + // if (getAuthorization()) { + // data = JSON.parse(getAuthorization()) + // } else { + // data = { userInfo: { is_real: 0 } } + // } + + // // 判断当前窗口是白名单,如果是则不重定向路由 + // if (type === 'agentpages' && !whiteList.includes(url) && !data.userInfo.is_real) { + // uni.showModal({ + // title: '提示', + // content: '请先实名认证', + // showCancel: true, + // success({ confirm }) { + // if (confirm) { + // uni.navigateTo({ + // url: '/pages/mine/authentication' + // }) + // } + // } + // }) + // return false + // } + + return e + }, + fail(err) { + // 失败回调拦截 + console.log(err) + } + }) + }) +} diff --git a/src/share.vue b/src/share.vue new file mode 100644 index 0000000..49c7feb --- /dev/null +++ b/src/share.vue @@ -0,0 +1,257 @@ + + + + + diff --git a/src/static/bg1.png b/src/static/bg1.png new file mode 100644 index 0000000..b208f6d Binary files /dev/null and b/src/static/bg1.png differ diff --git a/src/static/card.png b/src/static/card.png new file mode 100644 index 0000000..ffbbe99 Binary files /dev/null and b/src/static/card.png differ diff --git a/src/static/invite.jpg b/src/static/invite.jpg new file mode 100644 index 0000000..00113f5 Binary files /dev/null and b/src/static/invite.jpg differ diff --git a/src/static/logo-bg.png b/src/static/logo-bg.png new file mode 100644 index 0000000..a425dae Binary files /dev/null and b/src/static/logo-bg.png differ diff --git a/src/static/logo-tran.png b/src/static/logo-tran.png new file mode 100644 index 0000000..a5f7434 Binary files /dev/null and b/src/static/logo-tran.png differ diff --git a/src/static/logo.png b/src/static/logo.png new file mode 100644 index 0000000..ff95dd9 Binary files /dev/null and b/src/static/logo.png differ diff --git a/src/static/password.png b/src/static/password.png new file mode 100644 index 0000000..64e0364 Binary files /dev/null and b/src/static/password.png differ diff --git a/src/static/redpacket.png b/src/static/redpacket.png new file mode 100644 index 0000000..f172925 Binary files /dev/null and b/src/static/redpacket.png differ diff --git a/src/static/tabbar/grxx-select.png b/src/static/tabbar/grxx-select.png new file mode 100644 index 0000000..320f83a Binary files /dev/null and b/src/static/tabbar/grxx-select.png differ diff --git a/src/static/tabbar/grxx.png b/src/static/tabbar/grxx.png new file mode 100644 index 0000000..9e4775f Binary files /dev/null and b/src/static/tabbar/grxx.png differ diff --git a/src/static/tabbar/tpxj-select.png b/src/static/tabbar/tpxj-select.png new file mode 100644 index 0000000..a15d824 Binary files /dev/null and b/src/static/tabbar/tpxj-select.png differ diff --git a/src/static/tabbar/tpxj.png b/src/static/tabbar/tpxj.png new file mode 100644 index 0000000..adc9a50 Binary files /dev/null and b/src/static/tabbar/tpxj.png differ diff --git a/src/static/tabbar/wdxj-select.png b/src/static/tabbar/wdxj-select.png new file mode 100644 index 0000000..dd9de98 Binary files /dev/null and b/src/static/tabbar/wdxj-select.png differ diff --git a/src/static/tabbar/wdxj.png b/src/static/tabbar/wdxj.png new file mode 100644 index 0000000..22b15d5 Binary files /dev/null and b/src/static/tabbar/wdxj.png differ diff --git a/src/static/tabbar/xjjg-select.png b/src/static/tabbar/xjjg-select.png new file mode 100644 index 0000000..7a833ae Binary files /dev/null and b/src/static/tabbar/xjjg-select.png differ diff --git a/src/static/tabbar/xjjg.png b/src/static/tabbar/xjjg.png new file mode 100644 index 0000000..4067273 Binary files /dev/null and b/src/static/tabbar/xjjg.png differ diff --git a/src/static/tabbar/xjlb-select.png b/src/static/tabbar/xjlb-select.png new file mode 100644 index 0000000..5f29c4c Binary files /dev/null and b/src/static/tabbar/xjlb-select.png differ diff --git a/src/static/tabbar/xjlb.png b/src/static/tabbar/xjlb.png new file mode 100644 index 0000000..843e2b3 Binary files /dev/null and b/src/static/tabbar/xjlb.png differ diff --git a/src/static/user.png b/src/static/user.png new file mode 100644 index 0000000..2d0d076 Binary files /dev/null and b/src/static/user.png differ diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..86da23d --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,10 @@ +import { createPinia } from 'pinia' +import { createUnistorage } from 'pinia-plugin-unistorage' + +const store = createPinia() +// 使用该插件 +// 关键代码 👇 +store.use(createUnistorage()) + +//导出 +export default store diff --git a/src/store/user.ts b/src/store/user.ts new file mode 100644 index 0000000..2f16b3d --- /dev/null +++ b/src/store/user.ts @@ -0,0 +1,92 @@ +// 定义组合式API仓库 +import { defineStore } from 'pinia' +import { getPrefixName } from '@/config' + +interface userInfoStoreInt { + [n: string]: any +} +export default defineStore( + getPrefixName('user'), + () => { + const token = ref('') + const isShowPrize = ref(false) + const useType = ref('client') + const userInfo = ref({}) + const accountInfo = reactive({ + can_switch: false, + client: { + account: '', + password: '' + }, + agent: { + account: '', + password: '' + } + }) + const bankCard = ref({}) + + const checkLogin = computed(() => token.value !== '') + + function logOut() { + token.value = '' + + if (useType.value === 'client') { + accountInfo.client = { account: '', password: '' } + } else { + accountInfo.agent = { account: '', password: '' } + } + useType.value = 'client' + + userInfo.value = {} + bankCard.value = {} + uni.clearStorageSync() + + uni.showToast({ + icon: 'none', + title: '退出成功', + mask: true, + success() { + setTimeout(() => uni.reLaunch({ url: 'pages/login/login' }), 1000) + } + }) + } + + return { + token, + accountInfo, + isShowPrize, + useType, + userInfo, + bankCard, + checkLogin, + logOut + } + }, + { + unistorage: { + serializer: { + // 序列化,默认为 JSON.stringify + serialize(v) { + return JSON.stringify(v) + }, + // 反序列化,默认为 JSON.parse + deserialize(v) { + return JSON.parse(v) + } + } + } // 开启后对 state 的数据读写都将持久化 + // unistorage: { + // key: 'userInfo', // 缓存的键,默认为该 store 的 id,这里是 main, + // paths: ['userInfo.token'], // 需要缓存的路径,这里设置 foo 和 nested 下的 data 会被缓存 + // // 初始化恢复前触发 + // beforeRestore(ctx: any) { + // console.log(ctx) + // }, + // // 初始化恢复后触发 + // afterRestore(ctx: any) { + // console.log('ctx', ctx) + // }, + + // }, + } +) diff --git a/src/types/auto-imports.d.ts b/src/types/auto-imports.d.ts new file mode 100644 index 0000000..898474f --- /dev/null +++ b/src/types/auto-imports.d.ts @@ -0,0 +1,180 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +export {} +declare global { + const EffectScope: typeof import('vue')['EffectScope'] + const computed: typeof import('vue')['computed'] + const createApp: typeof import('vue')['createApp'] + const customRef: typeof import('vue')['customRef'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const effectScope: typeof import('vue')['effectScope'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const h: typeof import('vue')['h'] + const inject: typeof import('vue')['inject'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const markRaw: typeof import('vue')['markRaw'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onAddToFavorites: typeof import('@dcloudio/uni-app')['onAddToFavorites'] + const onBackPress: typeof import('@dcloudio/uni-app')['onBackPress'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onError: typeof import('@dcloudio/uni-app')['onError'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onHide: typeof import('@dcloudio/uni-app')['onHide'] + const onLaunch: typeof import('@dcloudio/uni-app')['onLaunch'] + const onLoad: typeof import('@dcloudio/uni-app')['onLoad'] + const onMounted: typeof import('vue')['onMounted'] + const onNavigationBarButtonTap: typeof import('@dcloudio/uni-app')['onNavigationBarButtonTap'] + const onNavigationBarSearchInputChanged: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputChanged'] + const onNavigationBarSearchInputClicked: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputClicked'] + const onNavigationBarSearchInputConfirmed: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputConfirmed'] + const onNavigationBarSearchInputFocusChanged: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputFocusChanged'] + const onPageNotFound: typeof import('@dcloudio/uni-app')['onPageNotFound'] + const onPageScroll: typeof import('@dcloudio/uni-app')['onPageScroll'] + const onPullDownRefresh: typeof import('@dcloudio/uni-app')['onPullDownRefresh'] + const onReachBottom: typeof import('@dcloudio/uni-app')['onReachBottom'] + const onReady: typeof import('@dcloudio/uni-app')['onReady'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onResize: typeof import('@dcloudio/uni-app')['onResize'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onShareAppMessage: typeof import('@dcloudio/uni-app')['onShareAppMessage'] + const onShareTimeline: typeof import('@dcloudio/uni-app')['onShareTimeline'] + const onShow: typeof import('@dcloudio/uni-app')['onShow'] + const onTabItemTap: typeof import('@dcloudio/uni-app')['onTabItemTap'] + const onThemeChange: typeof import('@dcloudio/uni-app')['onThemeChange'] + const onUnhandledRejection: typeof import('@dcloudio/uni-app')['onUnhandledRejection'] + const onUnload: typeof import('@dcloudio/uni-app')['onUnload'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] + const provide: typeof import('vue')['provide'] + const reactive: typeof import('vue')['reactive'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const toRaw: typeof import('vue')['toRaw'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const toValue: typeof import('vue')['toValue'] + const triggerRef: typeof import('vue')['triggerRef'] + const unref: typeof import('vue')['unref'] + const useAttrs: typeof import('vue')['useAttrs'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVars: typeof import('vue')['useCssVars'] + const useId: typeof import('vue')['useId'] + const useModel: typeof import('vue')['useModel'] + const useSlots: typeof import('vue')['useSlots'] + const useTemplateRef: typeof import('vue')['useTemplateRef'] + const watch: typeof import('vue')['watch'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] +} +// for type re-export +declare global { + // @ts-ignore + export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' + import('vue') +} +// for vue template auto import +import { UnwrapRef } from 'vue' +declare module 'vue' { + interface ComponentCustomProperties { + readonly EffectScope: UnwrapRef + readonly computed: UnwrapRef + readonly createApp: UnwrapRef + readonly customRef: UnwrapRef + readonly defineAsyncComponent: UnwrapRef + readonly defineComponent: UnwrapRef + readonly effectScope: UnwrapRef + readonly getCurrentInstance: UnwrapRef + readonly getCurrentScope: UnwrapRef + readonly h: UnwrapRef + readonly inject: UnwrapRef + readonly isProxy: UnwrapRef + readonly isReactive: UnwrapRef + readonly isReadonly: UnwrapRef + readonly isRef: UnwrapRef + readonly markRaw: UnwrapRef + readonly nextTick: UnwrapRef + readonly onActivated: UnwrapRef + readonly onAddToFavorites: UnwrapRef + readonly onBackPress: UnwrapRef + readonly onBeforeMount: UnwrapRef + readonly onBeforeUnmount: UnwrapRef + readonly onBeforeUpdate: UnwrapRef + readonly onDeactivated: UnwrapRef + readonly onError: UnwrapRef + readonly onErrorCaptured: UnwrapRef + readonly onHide: UnwrapRef + readonly onLaunch: UnwrapRef + readonly onLoad: UnwrapRef + readonly onMounted: UnwrapRef + readonly onNavigationBarButtonTap: UnwrapRef + readonly onNavigationBarSearchInputChanged: UnwrapRef + readonly onNavigationBarSearchInputClicked: UnwrapRef + readonly onNavigationBarSearchInputConfirmed: UnwrapRef + readonly onNavigationBarSearchInputFocusChanged: UnwrapRef + readonly onPageNotFound: UnwrapRef + readonly onPageScroll: UnwrapRef + readonly onPullDownRefresh: UnwrapRef + readonly onReachBottom: UnwrapRef + readonly onReady: UnwrapRef + readonly onRenderTracked: UnwrapRef + readonly onRenderTriggered: UnwrapRef + readonly onResize: UnwrapRef + readonly onScopeDispose: UnwrapRef + readonly onServerPrefetch: UnwrapRef + readonly onShareAppMessage: UnwrapRef + readonly onShareTimeline: UnwrapRef + readonly onShow: UnwrapRef + readonly onTabItemTap: UnwrapRef + readonly onThemeChange: UnwrapRef + readonly onUnhandledRejection: UnwrapRef + readonly onUnload: UnwrapRef + readonly onUnmounted: UnwrapRef + readonly onUpdated: UnwrapRef + readonly onWatcherCleanup: UnwrapRef + readonly provide: UnwrapRef + readonly reactive: UnwrapRef + readonly readonly: UnwrapRef + readonly ref: UnwrapRef + readonly resolveComponent: UnwrapRef + readonly shallowReactive: UnwrapRef + readonly shallowReadonly: UnwrapRef + readonly shallowRef: UnwrapRef + readonly toRaw: UnwrapRef + readonly toRef: UnwrapRef + readonly toRefs: UnwrapRef + readonly toValue: UnwrapRef + readonly triggerRef: UnwrapRef + readonly unref: UnwrapRef + readonly useAttrs: UnwrapRef + readonly useCssModule: UnwrapRef + readonly useCssVars: UnwrapRef + readonly useId: UnwrapRef + readonly useModel: UnwrapRef + readonly useSlots: UnwrapRef + readonly useTemplateRef: UnwrapRef + readonly watch: UnwrapRef + readonly watchEffect: UnwrapRef + readonly watchPostEffect: UnwrapRef + readonly watchSyncEffect: UnwrapRef + } +} diff --git a/src/types/env.d.ts b/src/types/env.d.ts new file mode 100644 index 0000000..7583e5f --- /dev/null +++ b/src/types/env.d.ts @@ -0,0 +1,13 @@ +/// +/// +/// +/// + +declare module '*.vue' { + import { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component +} + +declare module 'uview-plus' +declare module 'feng-uniapp-exploit' diff --git a/src/types/global.d.ts b/src/types/global.d.ts new file mode 100644 index 0000000..e85aac8 --- /dev/null +++ b/src/types/global.d.ts @@ -0,0 +1,29 @@ +/* eslint-disable prettier/prettier */ + +declare global { + type useType = 'client' | 'agent' + + /** + * 公共的路径 + * @author shenname + * @license MIT + * @param { string } fileName 文件名称 + * @param { string } filePath 文件路径 + * @example + * fileName: images.png + * filePath: images + */ + interface imgUrlInt { + fileName: string + filePath?: string + } + + interface pageType { + page: number + limit: number + total?: number + } + +} + +export { } diff --git a/src/uni.scss b/src/uni.scss new file mode 100644 index 0000000..0703013 --- /dev/null +++ b/src/uni.scss @@ -0,0 +1,119 @@ +@import 'uview-plus/theme.scss'; +// @use 'uview-plus/theme.scss'; + +#app { + box-sizing: border-box; + background-color: #f5f5f5 +} + +/* 颜色变量 */ + +/*============================= 文字尺寸 =============================*/ +$font-size-20: 20rpx; +$font-size-22: 22rpx; +$font-size-24: 24rpx; +$font-size-26: 26rpx; +$font-size-28: 28rpx; +$font-size-30: 30rpx; +$font-size-32: 32rpx; +$font-size-34: 34rpx; +$font-size-36: 36rpx; +$font-size-40: 40rpx; + +image { + width: 100%; + height: 100%; + box-sizing: border-box; +} + +view { + box-sizing: border-box; +} + +/*============================= 弹性盒子 =============================*/ +%flex-base { + display: flex; + flex-wrap: nowrap; +} + +$flex-way: ( + start, + flex-start), + (center, center), + (end, flex-end), + (between, space-between), + (around, space-around), + (evenly, space-evenly +); + +@mixin flex-algin($align) { + @each $way, $justify in $flex-way { + &-#{$way} { + @if $way !=$align { + @if $way !=$align { + @extend %flex-base; + align-items: $align; + justify-content: $justify; + } + } + } + } +} + +.flex { + @extend %flex-base; + align-items: center; + justify-content: center; + + @each $way, $justify in (start, flex-start), (center, center), (end, flex-end) { + &-#{$way} { + @include flex-algin($justify); + } + } +} + +[class*="flex-"], +[class^="flex"] { + &.nowrap { + flex-wrap: nowrap; + } + + &.stretch { + align-items: stretch; + } + + @each $direction, $name in (row, direction), (column, direction), (wrap, wrap) { + &.#{$direction} { + flex-#{$name}: $direction; + + &-reverse { + flex-#{$name}: '#{$direction}-reverse'; + } + } + } +} + +@for $i from 1 through 4 { + .flex#{$i} { + flex: $i; + } +} + +/*============================= 文字溢出 =============================*/ +.text-ellipsis { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + + @for $i from 2 through 4 { + &-#{$i} { + overflow: hidden; + white-space: normal; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + line-clamp: 1; + -webkit-line-clamp: $i; + } + } +} \ No newline at end of file diff --git a/src/utils/common.ts b/src/utils/common.ts new file mode 100644 index 0000000..ee62fac --- /dev/null +++ b/src/utils/common.ts @@ -0,0 +1,45 @@ +/** + * 获取用户头像地址 + * @author shenname + * @license MIT + * @param { string } url 头像地址 + * @returns { string } + */ +export const getHeaderImage = (url?: string) => { + if (url) { + return import.meta.env.VITE_APP_BASE_URL + url + } else { + return 'http://cdn-pos.lingji.vip/static/system/headimg.png' + } +} + +/** + * 获取图片地址 + * @author shenname + * @license MIT + * @param { string } url 图片地址 + * @returns { string } + */ +export const getImageUrl = (url?: string) => { + return import.meta.env.VITE_APP_BASE_URL + url +} + +/** + * 获取文件相对路径、URL + * @author shenname + * @license MIT + * @param { string } fileName 文件名称 | 相对路径 + * @param { string } [filePath=images] filePath 文件在 /static 下的路径 获取URL时不传 + * @example + * imgUrl('a.png') + * imgUrl('a.png', '/public/') + * imgUrl('/upload/images/img.png') + * @returns {string} + */ +export const fileUrl = (fileName: string, filePath: string = 'images'): string => { + if (/[ `!@#$%^&*()_+\-=\[\]{};':"\\|,<>\/?~]/.test(fileName)) { + return import.meta.env.VITE_APP_BASE_URL + fileName + } else { + return `http://cdn-pos.lingji.vip/static/${filePath}/${fileName}` + } +} diff --git a/src/utils/http.ts b/src/utils/http.ts new file mode 100644 index 0000000..c5445c5 --- /dev/null +++ b/src/utils/http.ts @@ -0,0 +1,69 @@ +import useUserStore from '../store/user' + +interface ResponseOptions { + url: string + headers?: { [key: string]: string } + method?: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT' + data?: { [key: string]: any } + isSinglePost?: boolean +} + +const userStore = useUserStore() + +export const request = { + isLock: false, + http({ url = '', headers = {}, data = {}, method = 'POST', isSinglePost = false }: ResponseOptions) { + const _this = this + + return new Promise(function (resolve, reject) { + if (isSinglePost && _this.isLock) { + reject({ message: '加载中' }) + } + _this.isLock = true + + // #ifdef APP-PLUS + url = import.meta.env.VITE_APP_BASE_URL + url + // #endif + // #ifdef H5 + url = import.meta.env.VITE_APP_BASE_PRE + url + // #endif + + const header = Object.assign({ 'content-type': 'application/json', Authorization: '' }, headers) + + if (userStore.token) { + header['Authorization'] = 'Bearer' + userStore.token + } + + uni.request({ + url, + header, + method, + data, + success(res) { + const data = res.data as { code: number; data: object; msg: string } + switch (data.code) { + case 1005: + uni.showToast({ title: '登录状态已失效,请重新登录!', icon: 'none' }) + setTimeout(() => uni.navigateTo({ url: 'pages/login/login' }), 1000) + break + case 200: + resolve(res.data) + break + default: + uni.showToast({ title: data.msg, icon: 'none', mask: true }) + reject(res.data) + break + } + }, + fail(err) { + uni.showToast({ title: '网络错误', icon: 'none' }) + reject(err) + }, + complete() { + _this.controller = null + _this.isLock = false + } + }) + }) + } +} diff --git a/src/utils/rules.ts b/src/utils/rules.ts new file mode 100644 index 0000000..f63dd6f --- /dev/null +++ b/src/utils/rules.ts @@ -0,0 +1,6 @@ +// 验证密码 +export function checkPassword(password: string) { + if (password.trim() === '') return false + + return /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{8,16}$/.test(password) +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..41eaa5b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "extends": "@vue/tsconfig/tsconfig.json", + "compilerOptions": { + "sourceMap": true, + "baseUrl": ".", + "paths": { + "@/*": [ + "./src/*" + ] + }, + "lib": [ + "esnext", + "dom" + ], + "types": [ + "vite/client", + "@dcloudio/types", + ], + "typeRoots": [ + "src/**/*.d.ts" + ] + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + "src/**/*.vue", + "src/types/*.d.ts" + ] +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..66a94eb --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,45 @@ +import { defineConfig, loadEnv } from 'vite' +import uni from '@dcloudio/vite-plugin-uni' +import AutoImport from 'unplugin-auto-import/vite' + +import path from 'path' +const pathSrc = path.resolve(__dirname, 'src') + +// https://vitejs.dev/config/ +export default defineConfig(({ mode }) => { + const { VITE_APP_BASE_URL, VITE_APP_BASE_PRE } = loadEnv(mode, process.cwd()) + + return { + transpileDependencies: ['uview-plus'], + resolve: { + // 别名 + alias: { + '@': path.join(__dirname, './src') + } + }, + plugins: [ + uni(), + AutoImport({ + // imports: ['vue', 'uni-app', { 'feng-uniapp-exploit': ['default'] }, { 'src/utils': ['default'] }], + imports: ['vue', 'uni-app'], + vueTemplate: true, + dts: path.resolve(pathSrc, 'types', 'auto-imports.d.ts') + }) + ], + // build: { + // rollupOptions: { + // external: ['feng-exploit-plus'] + // } + // }, + server: { + proxy: { + [VITE_APP_BASE_PRE]: { + target: VITE_APP_BASE_URL, + ws: true, + changeOrigin: true, + rewrite: (path) => path.replace(new RegExp('^' + VITE_APP_BASE_PRE), '') + } + } + } + } +})