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, // 防止
+
+
+
+ ${title}
+
+
+`;
+ 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 @@
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+ {{ '2024年度学生会主席选举' }}
+ 进行中
+
+
+
+ {{ '投票时间:2024-03-01 至 2024-03-07' }}
+
+
+
+
+
+
+
+
+
+
+ 陈佳怡
+
+ 未当选
+
+ 得票数:286
+
+
+
+
+ 60%
+
+
+
+
+
+
+ 陈佳怡
+ 当选
+
+
+ 得票数:286
+
+
+
+
+ 60%
+
+
+ 查看投票详情
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+ 联系客服
+
+
+
+
+
+
+
+ {{ cv.title }}
+
+
+
+
+
+
+
+
+
+
+ {{ phone }}
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+ 我的省钱报告
+
+
+ 累计节省手续费
+
+
+
+ 预计最高还能省
+
+
+
+
+ 累计综合收款费率
+ {{ data.cumulative }}%
+
+
+
+
+
+ 我的订单
+
+ 查看全部
+
+
+
+
+
+
+
+
+ 待付款
+
+
+
+
+
+ 待发货
+
+
+
+
+
+ 待收货
+
+
+
+
+
+ 已完成
+
+
+
+
+
+
+ 其它
+
+
+
+
+
+
+
+ {{ v.label }}
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+ 2024年度董事会成员选举
+ 投票开始时间:2024年3月15日 18:00
+ 投票截止时间:2024年3月15日 18:00
+
+
+
+
+
+
+
+ {{ row.name }}
+
+
+ {{ row.class }}
+
+
+
+
+
+ {{ item.butname }}
+
+
+
+
+
+
+
+ 全部同意
+ 提交投票
+
+
+
+
+
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), '')
+ }
+ }
+ }
+ }
+})