Compare commits

...

2 Commits

Author SHA1 Message Date
ecc6cca6c1 tempp 2025-03-14 04:57:49 +08:00
d88388d04b 新版本 2025-03-14 03:40:55 +08:00
149 changed files with 6373 additions and 20930 deletions

37
.cursorrules Normal file
View File

@@ -0,0 +1,37 @@
// Uniapp Vue 3 best practices
const vue3CompositionApiBestPractices = [
"Use setup() function for component logic",
"Utilize ref and reactive for reactive state",
"Implement computed properties with computed()",
"Use watch and watchEffect for side effects",
"Implement lifecycle hooks with onMounted, onUpdated, etc.",
"Utilize provide/inject for dependency injection",
];
// Folder structure
const folderStructure = `
src/
components/
composables/
views/
static/
ui/
App.vue
main.ts
`;
// Additional instructions
const additionalInstructions = `
1. Follow the uniapp vue3 version
2. Pay attention to the compatibility of mobile APP
3. Implement proper props and emits definitions
4. Utilize Vue 3's Teleport component when needed
5. Use Suspense for async components
6. Implement proper error handling
7. Follow Vue 3 style guide and naming conventions
8. Use Vite for fast development and building
`;

5
.env Normal file
View File

@@ -0,0 +1,5 @@
# 基础环境变量配置
VITE_APP_BASE_URL=https://www.quannengcha.com
VITE_APP_SHARE_URL=https://www.tianyuandata.com
# 默认环境配置
VITE_APP_DEBUG=false

5
.env.development Normal file
View File

@@ -0,0 +1,5 @@
# 开发环境配置
VITE_APP_BASE_URL=https://www.quannengcha.com
# 是否启用调试模式
VITE_APP_DEBUG=true

5
.env.production Normal file
View File

@@ -0,0 +1,5 @@
# 生产环境配置
VITE_APP_BASE_URL=https://www.quannengcha.com
# 关闭调试模式
VITE_APP_DEBUG=false

View File

@@ -5,7 +5,6 @@
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},

View File

@@ -1,251 +0,0 @@
{
"code": "00",
"data": {
"als_m12_id_max_monnum": "2",
"als_m1_cell_nbank_allnum": "1",
"als_d15_cell_nbank_week_allnum": "0",
"als_d15_id_nbank_allnum": "1",
"als_m12_id_min_monnum": "0",
"als_m3_id_max_monnum": "1",
"als_m12_cell_min_inteday": "14",
"als_m6_cell_nbank_max_inteday": "46",
"als_d15_cell_nbank_selfnum": "0",
"als_d15_cell_nbank_sloan_allnum": "1",
"als_m3_id_nbank_orgnum": "2",
"als_m12_cell_nbank_ca_allnum": "2",
"als_m1_id_nbank_week_orgnum": "0",
"als_m6_id_nbank_orgnum": "2",
"als_m3_cell_min_monnum": "1",
"als_m6_id_avg_monnum": "1.00",
"als_m6_cell_nbank_orgnum": "2",
"DataStrategy": {
"strategy_version": "1.0",
"product_type": "100099",
"strategy_id": "DTA_BR0007512",
"product_name": "预置_借贷意向验证",
"scene": "lend"
},
"als_d15_id_rel_orgnum": "1",
"als_m3_cell_nbank_cf_orgnum": "1",
"als_m12_cell_nbank_sloan_orgnum": "2",
"als_fst_id_nbank_inteday": "264",
"als_m1_id_nbank_allnum": "1",
"als_m6_cell_nbank_max_monnum": "1",
"als_m12_cell_caon_allnum": "2",
"als_m1_cell_nbank_cf_allnum": "1",
"als_m6_cell_nbank_night_allnum": "1",
"als_m12_id_nbank_night_allnum": "1",
"als_m3_cell_caon_orgnum": "1",
"als_m12_id_nbank_avg_monnum": "1.20",
"als_d15_cell_nbank_orgnum": "1",
"als_m12_id_nbank_cf_allnum": "4",
"als_m3_cell_nbank_orgnum": "2",
"als_m12_id_nbank_sloan_allnum": "6",
"als_m3_cell_min_inteday": "31",
"als_m6_cell_nbank_sloan_allnum": "4",
"als_m3_id_nbank_cf_allnum": "2",
"als_m6_cell_nbank_avg_monnum": "1.00",
"als_m12_id_nbank_max_monnum": "2",
"als_m1_cell_nbank_sloan_allnum": "1",
"als_m6_cell_nbank_ca_allnum": "2",
"als_m3_id_min_inteday": "31",
"als_m3_cell_caon_allnum": "1",
"als_m6_id_nbank_cf_orgnum": "1",
"als_m1_cell_nbank_night_orgnum": "0",
"als_m1_id_nbank_cf_orgnum": "1",
"als_m3_id_nbank_cf_orgnum": "1",
"als_d15_cell_nbank_night_orgnum": "0",
"als_m6_cell_nbank_night_orgnum": "1",
"als_m12_id_nbank_night_orgnum": "1",
"als_m3_id_nbank_avg_monnum": "1.00",
"als_m3_id_min_monnum": "1",
"als_lst_cell_nbank_csinteday": "1",
"als_m12_cell_nbank_max_inteday": "128",
"als_m6_cell_max_monnum": "1",
"als_d15_cell_nbank_night_allnum": "0",
"als_m12_cell_min_monnum": "0",
"als_m3_id_nbank_max_monnum": "1",
"als_m3_cell_max_monnum": "1",
"als_m1_id_rel_orgnum": "1",
"als_m1_cell_nbank_cf_orgnum": "1",
"als_m12_id_nbank_orgnum": "2",
"als_m1_cell_nbank_night_allnum": "0",
"als_m3_cell_nbank_allnum": "3",
"als_m3_id_nbank_night_allnum": "1",
"als_d15_cell_rel_orgnum": "1",
"als_d15_cell_nbank_cf_allnum": "1",
"als_m6_cell_nbank_selfnum": "0",
"als_m6_cell_caon_orgnum": "1",
"als_m12_cell_nbank_sloan_allnum": "6",
"als_m3_id_caon_allnum": "1",
"als_m12_cell_nbank_night_orgnum": "1",
"als_m12_id_min_inteday": "14",
"als_m12_id_nbank_sloan_orgnum": "2",
"als_m6_id_nbank_ca_allnum": "2",
"als_d15_id_nbank_orgnum": "1",
"als_m6_cell_nbank_cf_orgnum": "1",
"swift_number": "3034309_20241022220649_604904CBA19",
"als_m6_cell_nbank_tot_mons": "4",
"als_m12_id_tot_mons": "5",
"als_m12_id_avg_monnum": "1.20",
"als_m3_id_nbank_sloan_orgnum": "2",
"als_m3_cell_nbank_max_inteday": "38",
"als_m1_id_nbank_orgnum": "1",
"als_m12_id_nbank_cf_orgnum": "1",
"als_m1_cell_nbank_orgnum": "1",
"als_d15_cell_nbank_allnum": "1",
"als_m6_id_max_monnum": "1",
"als_m12_id_max_inteday": "128",
"als_m3_cell_nbank_selfnum": "0",
"als_m1_cell_nbank_selfnum": "0",
"als_m12_id_nbank_ca_allnum": "2",
"als_m6_id_nbank_night_allnum": "1",
"als_m3_id_nbank_max_inteday": "38",
"als_d15_id_nbank_selfnum": "0",
"als_m6_id_nbank_avg_monnum": "1.00",
"als_m12_cell_nbank_max_monnum": "2",
"als_m6_cell_min_monnum": "0",
"als_d15_cell_rel_allnum": "1",
"als_m6_cell_nbank_cf_allnum": "2",
"als_m12_id_nbank_selfnum": "0",
"als_m6_id_nbank_sloan_orgnum": "2",
"als_m1_cell_rel_allnum": "1",
"als_m12_id_nbank_max_inteday": "128",
"als_m6_cell_max_inteday": "46",
"als_m6_id_caon_allnum": "2",
"als_m6_id_nbank_night_orgnum": "1",
"als_lst_id_nbank_consnum": "1",
"als_m3_cell_nbank_max_monnum": "1",
"als_m6_id_rel_allnum": "2",
"als_m6_id_rel_orgnum": "1",
"als_m6_id_nbank_sloan_allnum": "4",
"als_m1_cell_rel_orgnum": "1",
"als_m6_cell_tot_mons": "4",
"als_m12_cell_nbank_min_inteday": "14",
"als_m12_id_nbank_ca_orgnum": "1",
"als_m6_id_caon_orgnum": "1",
"als_m3_id_max_inteday": "38",
"als_m6_cell_min_inteday": "31",
"als_m3_cell_nbank_sloan_orgnum": "2",
"als_m12_id_caon_orgnum": "1",
"als_m1_id_nbank_night_orgnum": "0",
"als_m6_cell_nbank_week_orgnum": "2",
"als_m3_cell_rel_orgnum": "1",
"als_m6_cell_rel_orgnum": "1",
"als_m3_id_nbank_sloan_allnum": "3",
"als_m12_cell_avg_monnum": "1.20",
"flag_datastrategy": "1",
"als_d15_id_nbank_cf_allnum": "1",
"als_m3_cell_max_inteday": "38",
"als_m12_cell_nbank_cf_allnum": "4",
"flag_applyloanstr": "1",
"als_m6_id_nbank_ca_orgnum": "1",
"als_m3_id_rel_orgnum": "1",
"als_m12_id_nbank_week_orgnum": "2",
"als_m3_cell_nbank_tot_mons": "3",
"als_m6_id_nbank_min_inteday": "31",
"als_m3_id_nbank_ca_orgnum": "1",
"als_m3_id_caon_orgnum": "1",
"als_m12_cell_nbank_week_allnum": "2",
"als_m1_cell_nbank_week_allnum": "0",
"als_m12_id_nbank_week_allnum": "2",
"als_m1_id_nbank_sloan_allnum": "1",
"als_m3_cell_nbank_min_inteday": "31",
"als_m12_id_nbank_allnum": "6",
"als_m1_id_nbank_cf_allnum": "1",
"als_m3_cell_avg_monnum": "1.00",
"als_m6_id_nbank_tot_mons": "4",
"als_lst_cell_nbank_inteday": "7",
"als_m3_id_nbank_ca_allnum": "1",
"als_m6_cell_caon_allnum": "2",
"als_m6_id_max_inteday": "46",
"als_m12_cell_rel_orgnum": "1",
"als_m12_id_nbank_tot_mons": "5",
"als_m12_cell_nbank_min_monnum": "0",
"als_m6_id_tot_mons": "4",
"als_m3_cell_tot_mons": "3",
"als_m3_id_nbank_night_orgnum": "1",
"als_m12_id_nbank_min_inteday": "14",
"als_m12_id_rel_allnum": "4",
"als_m6_cell_nbank_week_allnum": "2",
"als_m3_id_rel_allnum": "2",
"als_m12_cell_nbank_selfnum": "0",
"als_m12_id_caon_allnum": "2",
"als_m3_id_nbank_min_inteday": "31",
"als_m12_cell_tot_mons": "5",
"als_m12_id_rel_orgnum": "1",
"als_m6_cell_nbank_ca_orgnum": "1",
"als_d15_id_nbank_cf_orgnum": "1",
"als_m6_id_nbank_min_monnum": "0",
"als_m6_cell_avg_monnum": "1.00",
"als_m12_cell_nbank_night_allnum": "1",
"als_d15_cell_nbank_cf_orgnum": "1",
"als_m6_id_nbank_week_allnum": "2",
"als_m3_id_nbank_tot_mons": "3",
"als_m3_cell_nbank_night_orgnum": "1",
"als_m6_cell_nbank_sloan_orgnum": "2",
"als_m3_cell_nbank_ca_allnum": "1",
"als_m1_id_nbank_selfnum": "0",
"als_m6_id_nbank_cf_allnum": "2",
"als_m1_id_nbank_sloan_orgnum": "1",
"als_m6_id_nbank_week_orgnum": "2",
"als_m1_id_rel_allnum": "1",
"als_m3_cell_nbank_min_monnum": "1",
"als_m12_cell_max_monnum": "2",
"als_m12_cell_nbank_allnum": "6",
"als_d15_id_nbank_week_orgnum": "0",
"als_m1_id_nbank_night_allnum": "0",
"als_m6_id_min_inteday": "31",
"als_m12_cell_rel_allnum": "4",
"als_m6_id_nbank_max_inteday": "46",
"als_m12_cell_caon_orgnum": "1",
"als_d15_cell_nbank_week_orgnum": "0",
"als_d15_cell_nbank_sloan_orgnum": "1",
"als_m1_cell_nbank_sloan_orgnum": "1",
"als_m3_id_nbank_selfnum": "0",
"als_m1_cell_nbank_week_orgnum": "0",
"als_d15_id_nbank_sloan_allnum": "1",
"als_m3_cell_rel_allnum": "2",
"als_d15_id_nbank_sloan_orgnum": "1",
"als_m6_id_nbank_max_monnum": "1",
"als_m6_cell_nbank_allnum": "4",
"als_m3_cell_nbank_cf_allnum": "2",
"als_m1_id_nbank_week_allnum": "0",
"als_d15_id_rel_allnum": "1",
"als_m12_cell_nbank_tot_mons": "5",
"als_m3_id_tot_mons": "3",
"als_m6_cell_rel_allnum": "2",
"als_m12_cell_nbank_week_orgnum": "2",
"als_lst_id_nbank_inteday": "7",
"als_m6_id_nbank_selfnum": "0",
"als_m6_id_min_monnum": "0",
"code": "00",
"als_m12_cell_nbank_ca_orgnum": "1",
"als_m3_id_nbank_week_orgnum": "1",
"als_d15_id_nbank_week_allnum": "0",
"als_m3_id_nbank_min_monnum": "1",
"als_m3_id_avg_monnum": "1.00",
"als_d15_id_nbank_night_orgnum": "0",
"als_m3_cell_nbank_night_allnum": "1",
"als_fst_cell_nbank_inteday": "264",
"als_m3_id_nbank_week_allnum": "1",
"als_d15_id_nbank_night_allnum": "0",
"als_m12_cell_nbank_orgnum": "2",
"als_m3_cell_nbank_ca_orgnum": "1",
"als_m3_cell_nbank_sloan_allnum": "3",
"als_m12_cell_max_inteday": "128",
"als_m6_cell_nbank_min_inteday": "31",
"als_m12_id_nbank_min_monnum": "0",
"als_lst_id_nbank_csinteday": "1",
"als_lst_cell_nbank_consnum": "1",
"als_m3_cell_nbank_week_orgnum": "1",
"als_m12_cell_nbank_avg_monnum": "1.20",
"als_m3_id_nbank_allnum": "3",
"als_m6_id_nbank_allnum": "4",
"als_m12_cell_nbank_cf_orgnum": "1",
"als_m3_cell_nbank_avg_monnum": "1.00",
"als_m6_cell_nbank_min_monnum": "0",
"als_m3_cell_nbank_week_allnum": "1"
},
"flag_applyloanstr": "1"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +0,0 @@
const fs = require('node:fs')
const path = require('node:path')
// 读取文件路径
const filePath = path.join(__dirname, 'jdyx.txt')
// 输出文件路径
const outputFilePath = path.join(__dirname, 'output.json')
// 读取文件内容
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error('读取文件失败:', err)
return
}
const records = []
let currentRecord = ''
let capturing = false // 是否正在捕获一条记录
// 按字符处理数据
for (let i = 0; i < data.length; i++) {
const char = data[i]
// 检查是否找到 `als`
if (!capturing && data.slice(i, i + 3) === 'als') {
capturing = true // 开始捕获
currentRecord = 'als' // 初始化记录
i += 2 // 跳过已匹配的 "als"
continue
}
// 捕获状态下,遇到空格时结束记录
if (capturing) {
if (char === ' ') {
records.push(currentRecord) // 保存当前记录
capturing = false // 停止捕获
currentRecord = '' // 重置记录
}
else {
currentRecord += char // 继续捕获字符
}
}
}
// 将结果写入到JSON文件中
fs.writeFile(outputFilePath, JSON.stringify(records, null, 2), (err) => {
if (err) {
console.error('写入文件失败:', err)
}
else {
console.log(`记录已保存到文件: ${outputFilePath}`)
}
})
})

View File

@@ -1,41 +0,0 @@
const fs = require('node:fs')
const path = require('node:path')
// 读取文件路径
const inputFilePath = path.join(__dirname, 'output.json')
// 输出文件路径
const outputFilePath = path.join(__dirname, 'word_list.json')
// 读取JSON文件
fs.readFile(inputFilePath, 'utf8', (err, data) => {
if (err) {
console.error('读取文件失败:', err)
return
}
// 解析JSON内容
const records = JSON.parse(data)
// 用于存储所有分割后的单词
const wordSet = new Set()
// 遍历每个元素,将其按下划线分割
records.forEach((record) => {
const words = record.split('_')
words.forEach(word => wordSet.add(word)) // 去重
})
// 将Set转换为数组
const uniqueWords = Array.from(wordSet)
// 将结果写入到新的JSON文件
fs.writeFile(outputFilePath, JSON.stringify(uniqueWords, null, 2), (err) => {
if (err) {
console.error('写入文件失败:', err)
}
else {
console.log(`单词列表已保存到文件: ${outputFilePath}`)
}
})
})

View File

@@ -1,822 +0,0 @@
[
"als_d7_id_pdl_allnum",
"als_d7_id_pdl_orgnum",
"als_d7_id_caon_allnum",
"als_d7_id_caon_orgnum",
"als_d7_id_rel_allnum",
"als_d7_id_rel_orgnum",
"als_d7_id_caoff_allnum",
"als_d7_id_caoff_orgnum",
"als_d7_id_cooff_allnum",
"als_d7_id_cooff_orgnum",
"als_d7_id_af_allnum",
"als_d7_id_af_orgnum",
"als_d7_id_coon_allnum",
"als_d7_id_coon_orgnum",
"als_d7_id_oth_allnum",
"als_d7_id_oth_orgnum",
"als_d7_id_bank_selfnum",
"als_d7_id_bank_allnum",
"als_d7_id_bank_tra_allnum",
"als_d7_id_bank_ret_allnum",
"als_d7_id_bank_orgnum",
"als_d7_id_bank_tra_orgnum",
"als_d7_id_bank_ret_orgnum",
"als_d7_id_bank_week_allnum",
"als_d7_id_bank_week_orgnum",
"als_d7_id_bank_night_allnum",
"als_d7_id_bank_night_orgnum",
"als_d7_id_nbank_selfnum",
"als_d7_id_nbank_allnum",
"als_d7_id_nbank_p2p_allnum",
"als_d7_id_nbank_mc_allnum",
"als_d7_id_nbank_ca_allnum",
"als_d7_id_nbank_cf_allnum",
"als_d7_id_nbank_com_allnum",
"als_d7_id_nbank_oth_allnum",
"als_d7_id_nbank_nsloan_allnum",
"als_d7_id_nbank_autofin_allnum",
"als_d7_id_nbank_sloan_allnum",
"als_d7_id_nbank_cons_allnum",
"als_d7_id_nbank_finlea_allnum",
"als_d7_id_nbank_else_allnum",
"als_d7_id_nbank_orgnum",
"als_d7_id_nbank_p2p_orgnum",
"als_d7_id_nbank_mc_orgnum",
"als_d7_id_nbank_ca_orgnum",
"als_d7_id_nbank_cf_orgnum",
"als_d7_id_nbank_com_orgnum",
"als_d7_id_nbank_oth_orgnum",
"als_d7_id_nbank_nsloan_orgnum",
"als_d7_id_nbank_autofin_orgnum",
"als_d7_id_nbank_sloan_orgnum",
"als_d7_id_nbank_cons_orgnum",
"als_d7_id_nbank_finlea_orgnum",
"als_d7_id_nbank_else_orgnum",
"als_d7_id_nbank_week_allnum",
"als_d7_id_nbank_week_orgnum",
"als_d7_id_nbank_night_allnum",
"als_d7_id_nbank_night_orgnum",
"als_d7_cell_pdl_allnum",
"als_d7_cell_pdl_orgnum",
"als_d7_cell_caon_allnum",
"als_d7_cell_caon_orgnum",
"als_d7_cell_rel_allnum",
"als_d7_cell_rel_orgnum",
"als_d7_cell_caoff_allnum",
"als_d7_cell_caoff_orgnum",
"als_d7_cell_cooff_allnum",
"als_d7_cell_cooff_orgnum",
"als_d7_cell_af_allnum",
"als_d7_cell_af_orgnum",
"als_d7_cell_coon_allnum",
"als_d7_cell_coon_orgnum",
"als_d7_cell_oth_allnum",
"als_d7_cell_oth_orgnum",
"als_d7_cell_bank_selfnum",
"als_d7_cell_bank_allnum",
"als_d7_cell_bank_tra_allnum",
"als_d7_cell_bank_ret_allnum",
"als_d7_cell_bank_orgnum",
"als_d7_cell_bank_tra_orgnum",
"als_d7_cell_bank_ret_orgnum",
"als_d7_cell_bank_week_allnum",
"als_d7_cell_bank_week_orgnum",
"als_d7_cell_bank_night_allnum",
"als_d7_cell_bank_night_orgnum",
"als_d7_cell_nbank_selfnum",
"als_d7_cell_nbank_allnum",
"als_d7_cell_nbank_p2p_allnum",
"als_d7_cell_nbank_mc_allnum",
"als_d7_cell_nbank_ca_allnum",
"als_d7_cell_nbank_cf_allnum",
"als_d7_cell_nbank_com_allnum",
"als_d7_cell_nbank_oth_allnum",
"als_d7_cell_nbank_nsloan_allnum",
"als_d7_cell_nbank_autofin_allnum",
"als_d7_cell_nbank_sloan_allnum",
"als_d7_cell_nbank_cons_allnum",
"als_d7_cell_nbank_finlea_allnum",
"als_d7_cell_nbank_else_allnum",
"als_d7_cell_nbank_orgnum",
"als_d7_cell_nbank_p2p_orgnum",
"als_d7_cell_nbank_mc_orgnum",
"als_d7_cell_nbank_ca_orgnum",
"als_d7_cell_nbank_cf_orgnum",
"als_d7_cell_nbank_com_orgnum",
"als_d7_cell_nbank_oth_orgnum",
"als_d7_cell_nbank_nsloan_orgnum",
"als_d7_cell_nbank_autofin_orgnum",
"als_d7_cell_nbank_sloan_orgnum",
"als_d7_cell_nbank_cons_orgnum",
"als_d7_cell_nbank_finlea_orgnum",
"als_d7_cell_nbank_else_orgnum",
"als_d7_cell_nbank_week_allnum",
"als_d7_cell_nbank_week_orgnum",
"als_d7_cell_nbank_night_allnum",
"als_d7_cell_nbank_night_orgnum",
"als_d15_id_pdl_allnum",
"als_d15_id_pdl_orgnum",
"als_d15_id_caon_allnum",
"als_d15_id_caon_orgnum",
"als_d15_id_rel_allnum",
"als_d15_id_rel_orgnum",
"als_d15_id_caoff_allnum",
"als_d15_id_caoff_orgnum",
"als_d15_id_cooff_allnum",
"als_d15_id_cooff_orgnum",
"als_d15_id_af_allnum",
"als_d15_id_af_orgnum",
"als_d15_id_coon_allnum",
"als_d15_id_coon_orgnum",
"als_d15_id_oth_allnum",
"als_d15_id_oth_orgnum",
"als_d15_id_bank_selfnum",
"als_d15_id_bank_allnum",
"als_d15_id_bank_tra_allnum",
"als_d15_id_bank_ret_allnum",
"als_d15_id_bank_orgnum",
"als_d15_id_bank_tra_orgnum",
"als_d15_id_bank_ret_orgnum",
"als_d15_id_bank_week_allnum",
"als_d15_id_bank_week_orgnum",
"als_d15_id_bank_night_allnum",
"als_d15_id_bank_night_orgnum",
"als_d15_id_nbank_selfnum",
"als_d15_id_nbank_allnum",
"als_d15_id_nbank_p2p_allnum",
"als_d15_id_nbank_mc_allnum",
"als_d15_id_nbank_ca_allnum",
"als_d15_id_nbank_cf_allnum",
"als_d15_id_nbank_com_allnum",
"als_d15_id_nbank_oth_allnum",
"als_d15_id_nbank_nsloan_allnum",
"als_d15_id_nbank_autofin_allnum",
"als_d15_id_nbank_sloan_allnum",
"als_d15_id_nbank_cons_allnum",
"als_d15_id_nbank_finlea_allnum",
"als_d15_id_nbank_else_allnum",
"als_d15_id_nbank_orgnum",
"als_d15_id_nbank_p2p_orgnum",
"als_d15_id_nbank_mc_orgnum",
"als_d15_id_nbank_ca_orgnum",
"als_d15_id_nbank_cf_orgnum",
"als_d15_id_nbank_com_orgnum",
"als_d15_id_nbank_oth_orgnum",
"als_d15_id_nbank_nsloan_orgnum",
"als_d15_id_nbank_autofin_orgnum",
"als_d15_id_nbank_sloan_orgnum",
"als_d15_id_nbank_cons_orgnum",
"als_d15_id_nbank_finlea_orgnum",
"als_d15_id_nbank_else_orgnum",
"als_d15_id_nbank_week_allnum",
"als_d15_id_nbank_week_orgnum",
"als_d15_id_nbank_night_allnum",
"als_d15_id_nbank_night_orgnum",
"als_d15_cell_pdl_allnum",
"als_d15_cell_pdl_orgnum",
"als_d15_cell_caon_allnum",
"als_d15_cell_caon_orgnum",
"als_d15_cell_rel_allnum",
"als_d15_cell_rel_orgnum",
"als_d15_cell_caoff_allnum",
"als_d15_cell_caoff_orgnum",
"als_d15_cell_cooff_allnum",
"als_d15_cell_cooff_orgnum",
"als_d15_cell_af_allnum",
"als_d15_cell_af_orgnum",
"als_d15_cell_coon_allnum",
"als_d15_cell_coon_orgnum",
"als_d15_cell_oth_allnum",
"als_d15_cell_oth_orgnum",
"als_d15_cell_bank_selfnum",
"als_d15_cell_bank_allnum",
"als_d15_cell_bank_tra_allnum",
"als_d15_cell_bank_ret_allnum",
"als_d15_cell_bank_orgnum",
"als_d15_cell_bank_tra_orgnum",
"als_d15_cell_bank_ret_orgnum",
"als_d15_cell_bank_week_allnum",
"als_d15_cell_bank_week_orgnum",
"als_d15_cell_bank_night_allnum",
"als_d15_cell_bank_night_orgnum",
"als_d15_cell_nbank_selfnum",
"als_d15_cell_nbank_allnum",
"als_d15_cell_nbank_p2p_allnum",
"als_d15_cell_nbank_mc_allnum",
"als_d15_cell_nbank_ca_allnum",
"als_d15_cell_nbank_cf_allnum",
"als_d15_cell_nbank_com_allnum",
"als_d15_cell_nbank_oth_allnum",
"als_d15_cell_nbank_nsloan_allnum",
"als_d15_cell_nbank_autofin_allnum",
"als_d15_cell_nbank_sloan_allnum",
"als_d15_cell_nbank_cons_allnum",
"als_d15_cell_nbank_finlea_allnum",
"als_d15_cell_nbank_else_allnum",
"als_d15_cell_nbank_orgnum",
"als_d15_cell_nbank_p2p_orgnum",
"als_d15_cell_nbank_mc_orgnum",
"als_d15_cell_nbank_ca_orgnum",
"als_d15_cell_nbank_cf_orgnum",
"als_d15_cell_nbank_com_orgnum",
"als_d15_cell_nbank_oth_orgnum",
"als_d15_cell_nbank_nsloan_orgnum",
"als_d15_cell_nbank_autofin_orgnum",
"als_d15_cell_nbank_sloan_orgnum",
"als_d15_cell_nbank_cons_orgnum",
"als_d15_cell_nbank_finlea_orgnum",
"als_d15_cell_nbank_else_orgnum",
"als_d15_cell_nbank_week_allnum",
"als_d15_cell_nbank_week_orgnum",
"als_d15_cell_nbank_night_allnum",
"als_d15_cell_nbank_night_orgnum",
"als_m1_id_pdl_allnum",
"als_m1_id_pdl_orgnum",
"als_m1_id_caon_allnum",
"als_m1_id_caon_orgnum",
"als_m1_id_rel_allnum",
"als_m1_id_rel_orgnum",
"als_m1_id_caoff_allnum",
"als_m1_id_caoff_orgnum",
"als_m1_id_cooff_allnum",
"als_m1_id_cooff_orgnum",
"als_m1_id_af_allnum",
"als_m1_id_af_orgnum",
"als_m1_id_coon_allnum",
"als_m1_id_coon_orgnum",
"als_m1_id_oth_allnum",
"als_m1_id_oth_orgnum",
"als_m1_id_bank_selfnum",
"als_m1_id_bank_allnum",
"als_m1_id_bank_tra_allnum",
"als_m1_id_bank_ret_allnum",
"als_m1_id_bank_orgnum",
"als_m1_id_bank_tra_orgnum",
"als_m1_id_bank_ret_orgnum",
"als_m1_id_bank_week_allnum",
"als_m1_id_bank_week_orgnum",
"als_m1_id_bank_night_allnum",
"als_m1_id_bank_night_orgnum",
"als_m1_id_nbank_selfnum",
"als_m1_id_nbank_allnum",
"als_m1_id_nbank_p2p_allnum",
"als_m1_id_nbank_mc_allnum",
"als_m1_id_nbank_ca_allnum",
"als_m1_id_nbank_cf_allnum",
"als_m1_id_nbank_com_allnum",
"als_m1_id_nbank_oth_allnum",
"als_m1_id_nbank_nsloan_allnum",
"als_m1_id_nbank_autofin_allnum",
"als_m1_id_nbank_sloan_allnum",
"als_m1_id_nbank_cons_allnum",
"als_m1_id_nbank_finlea_allnum",
"als_m1_id_nbank_else_allnum",
"als_m1_id_nbank_orgnum",
"als_m1_id_nbank_p2p_orgnum",
"als_m1_id_nbank_mc_orgnum",
"als_m1_id_nbank_ca_orgnum",
"als_m1_id_nbank_cf_orgnum",
"als_m1_id_nbank_com_orgnum",
"als_m1_id_nbank_oth_orgnum",
"als_m1_id_nbank_nsloan_orgnum",
"als_m1_id_nbank_autofin_orgnum",
"als_m1_id_nbank_sloan_orgnum",
"als_m1_id_nbank_cons_orgnum",
"als_m1_id_nbank_finlea_orgnum",
"als_m1_id_nbank_else_orgnum",
"als_m1_id_nbank_week_allnum",
"als_m1_id_nbank_week_orgnum",
"als_m1_id_nbank_night_allnum",
"als_m1_id_nbank_night_orgnum",
"als_m1_cell_pdl_allnum",
"als_m1_cell_pdl_orgnum",
"als_m1_cell_caon_allnum",
"als_m1_cell_caon_orgnum",
"als_m1_cell_rel_allnum",
"als_m1_cell_rel_orgnum",
"als_m1_cell_caoff_allnum",
"als_m1_cell_caoff_orgnum",
"als_m1_cell_cooff_allnum",
"als_m1_cell_cooff_orgnum",
"als_m1_cell_af_allnum",
"als_m1_cell_af_orgnum",
"als_m1_cell_coon_allnum",
"als_m1_cell_coon_orgnum",
"als_m1_cell_oth_allnum",
"als_m1_cell_oth_orgnum",
"als_m1_cell_bank_selfnum",
"als_m1_cell_bank_allnum",
"als_m1_cell_bank_tra_allnum",
"als_m1_cell_bank_ret_allnum",
"als_m1_cell_bank_orgnum",
"als_m1_cell_bank_tra_orgnum",
"als_m1_cell_bank_ret_orgnum",
"als_m1_cell_bank_week_allnum",
"als_m1_cell_bank_week_orgnum",
"als_m1_cell_bank_night_allnum",
"als_m1_cell_bank_night_orgnum",
"als_m1_cell_nbank_selfnum",
"als_m1_cell_nbank_allnum",
"als_m1_cell_nbank_p2p_allnum",
"als_m1_cell_nbank_mc_allnum",
"als_m1_cell_nbank_ca_allnum",
"als_m1_cell_nbank_cf_allnum",
"als_m1_cell_nbank_com_allnum",
"als_m1_cell_nbank_oth_allnum",
"als_m1_cell_nbank_nsloan_allnum",
"als_m1_cell_nbank_autofin_allnum",
"als_m1_cell_nbank_sloan_allnum",
"als_m1_cell_nbank_cons_allnum",
"als_m1_cell_nbank_finlea_allnum",
"als_m1_cell_nbank_else_allnum",
"als_m1_cell_nbank_orgnum",
"als_m1_cell_nbank_p2p_orgnum",
"als_m1_cell_nbank_mc_orgnum",
"als_m1_cell_nbank_ca_orgnum",
"als_m1_cell_nbank_cf_orgnum",
"als_m1_cell_nbank_com_orgnum",
"als_m1_cell_nbank_oth_orgnum",
"als_m1_cell_nbank_nsloan_orgnum",
"als_m1_cell_nbank_autofin_orgnum",
"als_m1_cell_nbank_sloan_orgnum",
"als_m1_cell_nbank_cons_orgnum",
"als_m1_cell_nbank_finlea_orgnum",
"als_m1_cell_nbank_else_orgnum",
"als_m1_cell_nbank_week_allnum",
"als_m1_cell_nbank_week_orgnum",
"als_m1_cell_nbank_night_allnum",
"als_m1_cell_nbank_night_orgnum",
"als_m3_id_max_inteday",
"als_m3_id_min_inteday",
"als_m3_id_tot_mons",
"als_m3_id_avg_monnum",
"als_m3_id_max_monnum",
"als_m3_id_min_monnum",
"als_m3_id_pdl_allnum",
"als_m3_id_pdl_orgnum",
"als_m3_id_caon_allnum",
"als_m3_id_caon_orgnum",
"als_m3_id_rel_allnum",
"als_m3_id_rel_orgnum",
"als_m3_id_caoff_allnum",
"als_m3_id_caoff_orgnum",
"als_m3_id_cooff_allnum",
"als_m3_id_cooff_orgnum",
"als_m3_id_af_allnum",
"als_m3_id_af_orgnum",
"als_m3_id_coon_allnum",
"als_m3_id_coon_orgnum",
"als_m3_id_oth_allnum",
"als_m3_id_oth_orgnum",
"als_m3_id_bank_selfnum",
"als_m3_id_bank_allnum",
"als_m3_id_bank_tra_allnum",
"als_m3_id_bank_ret_allnum",
"als_m3_id_bank_orgnum",
"als_m3_id_bank_tra_orgnum",
"als_m3_id_bank_ret_orgnum",
"als_m3_id_bank_tot_mons",
"als_m3_id_bank_avg_monnum",
"als_m3_id_bank_max_monnum",
"als_m3_id_bank_min_monnum",
"als_m3_id_bank_max_inteday",
"als_m3_id_bank_min_inteday",
"als_m3_id_bank_week_allnum",
"als_m3_id_bank_week_orgnum",
"als_m3_id_bank_night_allnum",
"als_m3_id_bank_night_orgnum",
"als_m3_id_nbank_selfnum",
"als_m3_id_nbank_allnum",
"als_m3_id_nbank_p2p_allnum",
"als_m3_id_nbank_mc_allnum",
"als_m3_id_nbank_ca_allnum",
"als_m3_id_nbank_cf_allnum",
"als_m3_id_nbank_com_allnum",
"als_m3_id_nbank_oth_allnum",
"als_m3_id_nbank_nsloan_allnum",
"als_m3_id_nbank_autofin_allnum",
"als_m3_id_nbank_sloan_allnum",
"als_m3_id_nbank_cons_allnum",
"als_m3_id_nbank_finlea_allnum",
"als_m3_id_nbank_else_allnum",
"als_m3_id_nbank_orgnum",
"als_m3_id_nbank_p2p_orgnum",
"als_m3_id_nbank_mc_orgnum",
"als_m3_id_nbank_ca_orgnum",
"als_m3_id_nbank_cf_orgnum",
"als_m3_id_nbank_com_orgnum",
"als_m3_id_nbank_oth_orgnum",
"als_m3_id_nbank_nsloan_orgnum",
"als_m3_id_nbank_autofin_orgnum",
"als_m3_id_nbank_sloan_orgnum",
"als_m3_id_nbank_cons_orgnum",
"als_m3_id_nbank_finlea_orgnum",
"als_m3_id_nbank_else_orgnum",
"als_m3_id_nbank_tot_mons",
"als_m3_id_nbank_avg_monnum",
"als_m3_id_nbank_max_monnum",
"als_m3_id_nbank_min_monnum",
"als_m3_id_nbank_max_inteday",
"als_m3_id_nbank_min_inteday",
"als_m3_id_nbank_week_allnum",
"als_m3_id_nbank_week_orgnum",
"als_m3_id_nbank_night_allnum",
"als_m3_id_nbank_night_orgnum",
"als_m3_cell_max_inteday",
"als_m3_cell_min_inteday",
"als_m3_cell_tot_mons",
"als_m3_cell_avg_monnum",
"als_m3_cell_max_monnum",
"als_m3_cell_min_monnum",
"als_m3_cell_pdl_allnum",
"als_m3_cell_pdl_orgnum",
"als_m3_cell_caon_allnum",
"als_m3_cell_caon_orgnum",
"als_m3_cell_rel_allnum",
"als_m3_cell_rel_orgnum",
"als_m3_cell_caoff_allnum",
"als_m3_cell_caoff_orgnum",
"als_m3_cell_cooff_allnum",
"als_m3_cell_cooff_orgnum",
"als_m3_cell_af_allnum",
"als_m3_cell_af_orgnum",
"als_m3_cell_coon_allnum",
"als_m3_cell_coon_orgnum",
"als_m3_cell_oth_allnum",
"als_m3_cell_oth_orgnum",
"als_m3_cell_bank_selfnum",
"als_m3_cell_bank_allnum",
"als_m3_cell_bank_tra_allnum",
"als_m3_cell_bank_ret_allnum",
"als_m3_cell_bank_orgnum",
"als_m3_cell_bank_tra_orgnum",
"als_m3_cell_bank_ret_orgnum",
"als_m3_cell_bank_tot_mons",
"als_m3_cell_bank_avg_monnum",
"als_m3_cell_bank_max_monnum",
"als_m3_cell_bank_min_monnum",
"als_m3_cell_bank_max_inteday",
"als_m3_cell_bank_min_inteday",
"als_m3_cell_bank_week_allnum",
"als_m3_cell_bank_week_orgnum",
"als_m3_cell_bank_night_allnum",
"als_m3_cell_bank_night_orgnum",
"als_m3_cell_nbank_selfnum",
"als_m3_cell_nbank_allnum",
"als_m3_cell_nbank_p2p_allnum",
"als_m3_cell_nbank_mc_allnum",
"als_m3_cell_nbank_ca_allnum",
"als_m3_cell_nbank_cf_allnum",
"als_m3_cell_nbank_com_allnum",
"als_m3_cell_nbank_oth_allnum",
"als_m3_cell_nbank_nsloan_allnum",
"als_m3_cell_nbank_autofin_allnum",
"als_m3_cell_nbank_sloan_allnum",
"als_m3_cell_nbank_cons_allnum",
"als_m3_cell_nbank_finlea_allnum",
"als_m3_cell_nbank_else_allnum",
"als_m3_cell_nbank_orgnum",
"als_m3_cell_nbank_p2p_orgnum",
"als_m3_cell_nbank_mc_orgnum",
"als_m3_cell_nbank_ca_orgnum",
"als_m3_cell_nbank_cf_orgnum",
"als_m3_cell_nbank_com_orgnum",
"als_m3_cell_nbank_oth_orgnum",
"als_m3_cell_nbank_nsloan_orgnum",
"als_m3_cell_nbank_autofin_orgnum",
"als_m3_cell_nbank_sloan_orgnum",
"als_m3_cell_nbank_cons_orgnum",
"als_m3_cell_nbank_finlea_orgnum",
"als_m3_cell_nbank_else_orgnum",
"als_m3_cell_nbank_tot_mons",
"als_m3_cell_nbank_avg_monnum",
"als_m3_cell_nbank_max_monnum",
"als_m3_cell_nbank_min_monnum",
"als_m3_cell_nbank_max_inteday",
"als_m3_cell_nbank_min_inteday",
"als_m3_cell_nbank_week_allnum",
"als_m3_cell_nbank_week_orgnum",
"als_m3_cell_nbank_night_allnum",
"als_m3_cell_nbank_night_orgnum",
"als_m6_id_max_inteday",
"als_m6_id_min_inteday",
"als_m6_id_tot_mons",
"als_m6_id_avg_monnum",
"als_m6_id_max_monnum",
"als_m6_id_min_monnum",
"als_m6_id_pdl_allnum",
"als_m6_id_pdl_orgnum",
"als_m6_id_caon_allnum",
"als_m6_id_caon_orgnum",
"als_m6_id_rel_allnum",
"als_m6_id_rel_orgnum",
"als_m6_id_caoff_allnum",
"als_m6_id_caoff_orgnum",
"als_m6_id_cooff_allnum",
"als_m6_id_cooff_orgnum",
"als_m6_id_af_allnum",
"als_m6_id_af_orgnum",
"als_m6_id_coon_allnum",
"als_m6_id_coon_orgnum",
"als_m6_id_oth_allnum",
"als_m6_id_oth_orgnum",
"als_m6_id_bank_selfnum",
"als_m6_id_bank_allnum",
"als_m6_id_bank_tra_allnum",
"als_m6_id_bank_ret_allnum",
"als_m6_id_bank_orgnum",
"als_m6_id_bank_tra_orgnum",
"als_m6_id_bank_ret_orgnum",
"als_m6_id_bank_tot_mons",
"als_m6_id_bank_avg_monnum",
"als_m6_id_bank_max_monnum",
"als_m6_id_bank_min_monnum",
"als_m6_id_bank_max_inteday",
"als_m6_id_bank_min_inteday",
"als_m6_id_bank_week_allnum",
"als_m6_id_bank_week_orgnum",
"als_m6_id_bank_night_allnum",
"als_m6_id_bank_night_orgnum",
"als_m6_id_nbank_selfnum",
"als_m6_id_nbank_allnum",
"als_m6_id_nbank_p2p_allnum",
"als_m6_id_nbank_mc_allnum",
"als_m6_id_nbank_ca_allnum",
"als_m6_id_nbank_cf_allnum",
"als_m6_id_nbank_com_allnum",
"als_m6_id_nbank_oth_allnum",
"als_m6_id_nbank_nsloan_allnum",
"als_m6_id_nbank_autofin_allnum",
"als_m6_id_nbank_sloan_allnum",
"als_m6_id_nbank_cons_allnum",
"als_m6_id_nbank_finlea_allnum",
"als_m6_id_nbank_else_allnum",
"als_m6_id_nbank_orgnum",
"als_m6_id_nbank_p2p_orgnum",
"als_m6_id_nbank_mc_orgnum",
"als_m6_id_nbank_ca_orgnum",
"als_m6_id_nbank_cf_orgnum",
"als_m6_id_nbank_com_orgnum",
"als_m6_id_nbank_oth_orgnum",
"als_m6_id_nbank_nsloan_orgnum",
"als_m6_id_nbank_autofin_orgnum",
"als_m6_id_nbank_sloan_orgnum",
"als_m6_id_nbank_cons_orgnum",
"als_m6_id_nbank_finlea_orgnum",
"als_m6_id_nbank_else_orgnum",
"als_m6_id_nbank_tot_mons",
"als_m6_id_nbank_avg_monnum",
"als_m6_id_nbank_max_monnum",
"als_m6_id_nbank_min_monnum",
"als_m6_id_nbank_max_inteday",
"als_m6_id_nbank_min_inteday",
"als_m6_id_nbank_week_allnum",
"als_m6_id_nbank_week_orgnum",
"als_m6_id_nbank_night_allnum",
"als_m6_id_nbank_night_orgnum",
"als_m6_cell_max_inteday",
"als_m6_cell_min_inteday",
"als_m6_cell_tot_mons",
"als_m6_cell_avg_monnum",
"als_m6_cell_max_monnum",
"als_m6_cell_min_monnum",
"als_m6_cell_pdl_allnum",
"als_m6_cell_pdl_orgnum",
"als_m6_cell_caon_allnum",
"als_m6_cell_caon_orgnum",
"als_m6_cell_rel_allnum",
"als_m6_cell_rel_orgnum",
"als_m6_cell_caoff_allnum",
"als_m6_cell_caoff_orgnum",
"als_m6_cell_cooff_allnum",
"als_m6_cell_cooff_orgnum",
"als_m6_cell_af_allnum",
"als_m6_cell_af_orgnum",
"als_m6_cell_coon_allnum",
"als_m6_cell_coon_orgnum",
"als_m6_cell_oth_allnum",
"als_m6_cell_oth_orgnum",
"als_m6_cell_bank_selfnum",
"als_m6_cell_bank_allnum",
"als_m6_cell_bank_tra_allnum",
"als_m6_cell_bank_ret_allnum",
"als_m6_cell_bank_orgnum",
"als_m6_cell_bank_tra_orgnum",
"als_m6_cell_bank_ret_orgnum",
"als_m6_cell_bank_tot_mons",
"als_m6_cell_bank_avg_monnum",
"als_m6_cell_bank_max_monnum",
"als_m6_cell_bank_min_monnum",
"als_m6_cell_bank_max_inteday",
"als_m6_cell_bank_min_inteday",
"als_m6_cell_bank_week_allnum",
"als_m6_cell_bank_week_orgnum",
"als_m6_cell_bank_night_allnum",
"als_m6_cell_bank_night_orgnum",
"als_m6_cell_nbank_selfnum",
"als_m6_cell_nbank_allnum",
"als_m6_cell_nbank_p2p_allnum",
"als_m6_cell_nbank_mc_allnum",
"als_m6_cell_nbank_ca_allnum",
"als_m6_cell_nbank_cf_allnum",
"als_m6_cell_nbank_com_allnum",
"als_m6_cell_nbank_oth_allnum",
"als_m6_cell_nbank_nsloan_allnum",
"als_m6_cell_nbank_autofin_allnum",
"als_m6_cell_nbank_sloan_allnum",
"als_m6_cell_nbank_cons_allnum",
"als_m6_cell_nbank_finlea_allnum",
"als_m6_cell_nbank_else_allnum",
"als_m6_cell_nbank_orgnum",
"als_m6_cell_nbank_p2p_orgnum",
"als_m6_cell_nbank_mc_orgnum",
"als_m6_cell_nbank_ca_orgnum",
"als_m6_cell_nbank_cf_orgnum",
"als_m6_cell_nbank_com_orgnum",
"als_m6_cell_nbank_oth_orgnum",
"als_m6_cell_nbank_nsloan_orgnum",
"als_m6_cell_nbank_autofin_orgnum",
"als_m6_cell_nbank_sloan_orgnum",
"als_m6_cell_nbank_cons_orgnum",
"als_m6_cell_nbank_finlea_orgnum",
"als_m6_cell_nbank_else_orgnum",
"als_m6_cell_nbank_tot_mons",
"als_m6_cell_nbank_avg_monnum",
"als_m6_cell_nbank_max_monnum",
"als_m6_cell_nbank_min_monnum",
"als_m6_cell_nbank_max_inteday",
"als_m6_cell_nbank_min_inteday",
"als_m6_cell_nbank_week_allnum",
"als_m6_cell_nbank_week_orgnum",
"als_m6_cell_nbank_night_allnum",
"als_m6_cell_nbank_night_orgnum",
"als_m12_id_max_inteday",
"als_m12_id_min_inteday",
"als_m12_id_tot_mons",
"als_m12_id_avg_monnum",
"als_m12_id_max_monnum",
"als_m12_id_min_monnum",
"als_m12_id_pdl_allnum",
"als_m12_id_pdl_orgnum",
"als_m12_id_caon_allnum",
"als_m12_id_caon_orgnum",
"als_m12_id_rel_allnum",
"als_m12_id_rel_orgnum",
"als_m12_id_caoff_allnum",
"als_m12_id_caoff_orgnum",
"als_m12_id_cooff_allnum",
"als_m12_id_cooff_orgnum",
"als_m12_id_af_allnum",
"als_m12_id_af_orgnum",
"als_m12_id_coon_allnum",
"als_m12_id_coon_orgnum",
"als_m12_id_oth_allnum",
"als_m12_id_oth_orgnum",
"als_m12_id_bank_selfnum",
"als_m12_id_bank_allnum",
"als_m12_id_bank_tra_allnum",
"als_m12_id_bank_ret_allnum",
"als_m12_id_bank_orgnum",
"als_m12_id_bank_tra_orgnum",
"als_m12_id_bank_ret_orgnum",
"als_m12_id_bank_tot_mons",
"als_m12_id_bank_avg_monnum",
"als_m12_id_bank_max_monnum",
"als_m12_id_bank_min_monnum",
"als_m12_id_bank_max_inteday",
"als_m12_id_bank_min_inteday",
"als_m12_id_bank_week_allnum",
"als_m12_id_bank_week_orgnum",
"als_m12_id_bank_night_allnum",
"als_m12_id_bank_night_orgnum",
"als_m12_id_nbank_selfnum",
"als_m12_id_nbank_allnum",
"als_m12_id_nbank_p2p_allnum",
"als_m12_id_nbank_mc_allnum",
"als_m12_id_nbank_ca_allnum",
"als_m12_id_nbank_cf_allnum",
"als_m12_id_nbank_com_allnum",
"als_m12_id_nbank_oth_allnum",
"als_m12_id_nbank_nsloan_allnum",
"als_m12_id_nbank_autofin_allnum",
"als_m12_id_nbank_sloan_allnum",
"als_m12_id_nbank_cons_allnum",
"als_m12_id_nbank_finlea_allnum",
"als_m12_id_nbank_else_allnum",
"als_m12_id_nbank_orgnum",
"als_m12_id_nbank_p2p_orgnum",
"als_m12_id_nbank_mc_orgnum",
"als_m12_id_nbank_ca_orgnum",
"als_m12_id_nbank_cf_orgnum",
"als_m12_id_nbank_com_orgnum",
"als_m12_id_nbank_oth_orgnum",
"als_m12_id_nbank_nsloan_orgnum",
"als_m12_id_nbank_autofin_orgnum",
"als_m12_id_nbank_sloan_orgnum",
"als_m12_id_nbank_cons_orgnum",
"als_m12_id_nbank_finlea_orgnum",
"als_m12_id_nbank_else_orgnum",
"als_m12_id_nbank_tot_mons",
"als_m12_id_nbank_avg_monnum",
"als_m12_id_nbank_max_monnum",
"als_m12_id_nbank_min_monnum",
"als_m12_id_nbank_max_inteday",
"als_m12_id_nbank_min_inteday",
"als_m12_id_nbank_week_allnum",
"als_m12_id_nbank_week_orgnum",
"als_m12_id_nbank_night_allnum",
"als_m12_id_nbank_night_orgnum",
"als_m12_cell_max_inteday",
"als_m12_cell_min_inteday",
"als_m12_cell_tot_mons",
"als_m12_cell_avg_monnum",
"als_m12_cell_max_monnum",
"als_m12_cell_min_monnum",
"als_m12_cell_pdl_allnum",
"als_m12_cell_pdl_orgnum",
"als_m12_cell_caon_allnum",
"als_m12_cell_caon_orgnum",
"als_m12_cell_rel_allnum",
"als_m12_cell_rel_orgnum",
"als_m12_cell_caoff_allnum",
"als_m12_cell_caoff_orgnum",
"als_m12_cell_cooff_allnum",
"als_m12_cell_cooff_orgnum",
"als_m12_cell_af_allnum",
"als_m12_cell_af_orgnum",
"als_m12_cell_coon_allnum",
"als_m12_cell_coon_orgnum",
"als_m12_cell_oth_allnum",
"als_m12_cell_oth_orgnum",
"als_m12_cell_bank_selfnum",
"als_m12_cell_bank_allnum",
"als_m12_cell_bank_tra_allnum",
"als_m12_cell_bank_ret_allnum",
"als_m12_cell_bank_orgnum",
"als_m12_cell_bank_tra_orgnum",
"als_m12_cell_bank_ret_orgnum",
"als_m12_cell_bank_tot_mons",
"als_m12_cell_bank_avg_monnum",
"als_m12_cell_bank_max_monnum",
"als_m12_cell_bank_min_monnum",
"als_m12_cell_bank_max_inteday",
"als_m12_cell_bank_min_inteday",
"als_m12_cell_bank_week_allnum",
"als_m12_cell_bank_week_orgnum",
"als_m12_cell_bank_night_allnum",
"als_m12_cell_bank_night_orgnum",
"als_m12_cell_nbank_selfnum",
"als_m12_cell_nbank_allnum",
"als_m12_cell_nbank_p2p_allnum",
"als_m12_cell_nbank_mc_allnum",
"als_m12_cell_nbank_ca_allnum",
"als_m12_cell_nbank_cf_allnum",
"als_m12_cell_nbank_com_allnum",
"als_m12_cell_nbank_oth_allnum",
"als_m12_cell_nbank_nsloan_allnum",
"als_m12_cell_nbank_autofin_allnum",
"als_m12_cell_nbank_sloan_allnum",
"als_m12_cell_nbank_cons_allnum",
"als_m12_cell_nbank_finlea_allnum",
"als_m12_cell_nbank_else_allnum",
"als_m12_cell_nbank_orgnum",
"als_m12_cell_nbank_p2p_orgnum",
"als_m12_cell_nbank_mc_orgnum",
"als_m12_cell_nbank_ca_orgnum",
"als_m12_cell_nbank_cf_orgnum",
"als_m12_cell_nbank_com_orgnum",
"als_m12_cell_nbank_oth_orgnum",
"als_m12_cell_nbank_nsloan_orgnum",
"als_m12_cell_nbank_autofin_orgnum",
"als_m12_cell_nbank_sloan_orgnum",
"als_m12_cell_nbank_cons_orgnum",
"als_m12_cell_nbank_finlea_orgnum",
"als_m12_cell_nbank_else_orgnum",
"als_m12_cell_nbank_tot_mons",
"als_m12_cell_nbank_avg_monnum",
"als_m12_cell_nbank_max_monnum",
"als_m12_cell_nbank_min_monnum",
"als_m12_cell_nbank_max_inteday",
"als_m12_cell_nbank_min_inteday",
"als_m12_cell_nbank_week_allnum",
"als_m12_cell_nbank_week_orgnum",
"als_m12_cell_nbank_night_allnum",
"als_m12_cell_nbank_night_orgnum",
"als_fst_id_bank_inteday",
"als_fst_id_nbank_inteday",
"als_fst_cell_bank_inteday",
"als_fst_cell_nbank_inteday",
"als_lst_id_bank_inteday",
"als_lst_id_bank_consnum",
"als_lst_id_bank_csinteday",
"als_lst_id_nbank_inteday",
"als_lst_id_nbank_consnum",
"als_lst_id_nbank_csinteday",
"als_lst_cell_bank_inteday",
"als_lst_cell_bank_consnum",
"als_lst_cell_bank_csinteday",
"als_lst_cell_nbank_inteday",
"als_lst_cell_nbank_consnum",
"als_lst_cell_nbank_csinteday"
]

View File

@@ -1,51 +0,0 @@
const keyword = [
'als',
'd7', // 近7日
'id', // 身份证号
'pdl', // 线上小额现金贷
'allnum', // 次数
'orgnum', // 机构数、
'week', // 周末
'night', // 夜间申请
'caon', // 线上现金分期
'rel', // 信用卡(类信用卡)
'caoff', // 线下现金分期
'cooff', // 线下消费分期
'af', // 汽车金融
'coon', // 线上消费分期
'oth', // 申请其他
'bank', // 银行机构
'selfnum', // 本银行机构
'tra', // 传统银行
'ret', // 网络银行
'nbank', // 非银行机构
'p2p', // 改制机构
'mc', // 小贷机构
'ca', // 现金类分期机构
'cf', // 消费类分期机构
'com', // 代偿类分期机构
'nsloan', // 持牌网络小贷
'autofin', // 持牌汽车金融机构
'sloan', // 持牌小贷机构
'cons', // 持牌消费金融机构
'finlea', // 持牌融资租赁机构
'else', // 其他申请
'cell', // 10 按手机号查询,
'd15', // 近 15 天申
'm1', // 近 1 个月
'm3', // 3 个月
'max', // 最大
'inteday', // 间隔天数
'min', // 最小
'tot', // 申请记录
'mons', // 月份数
'avg', // 平均
'monnum', // 最大月
'm6', // 6 个月
'm12', // 12个月
'fst', // 最早
'lst', // 最近
'consnum', // 连续申请
'csinteday', // 连续申请持续天数
]
console.log(keyword)

View File

@@ -1,65 +0,0 @@
{
"msg": "查询成功",
"code": "0000",
"orderNo": "20241028112921367340619",
"data": {
"total": 1,
"datalist": [
{
"orgName": "海南省学宇思网络科技有限公司",
"pName": "刘福思",
"stockHolderItem": {
"orgHolderType": "自然人",
"investDate": "",
"investRate": "40%",
"subscriptAmt": "40.000000",
"orgHolderName": "刘福思"
},
"relationship": [
"lp",
"sh",
"tm"
],
"fsource": "",
"basicInfo": {
"regStatus": "存续",
"regCapital": "100.0000万人民币",
"reccap": 0,
"city": "海口市",
"industry_code": "I",
"industry": "互联网和相关服务",
"type": "1",
"staffList": {
"result": [
{
"name": "刘福思",
"type": "2",
"typeJoin": [
"执行董事兼总经理"
]
}
]
},
"nic_code": "I64",
"legalPersonName": "刘福思",
"regNumber": "460108011261916",
"creditCode": "91460108MADNY3F43W",
"province": "海南省",
"regorg": "海南省市场监督管理局",
"companyOrgType": "有限责任公司(自然人投资或控股)",
"revdate": "",
"estiblishTime": "2024-06-20",
"opscope": "一般经营项目品牌管理5G通信技术服务人工智能应用软件开发互联网安全服务量子计算技术服务技术服务、技术开发、技术咨询、技术交流、技术转让、技术推广网络技术服务专业设计服务互联网数据服务互联网销售除销售需要许可的商品食品互联网销售仅销售预包装食品软件开发动漫游戏开发计算机软硬件及辅助设备零售计算机软硬件及辅助设备批发计算器设备销售机械设备销售五金产品零售五金产品批发电子产品销售人工智能硬件销售通信设备销售光通信设备销售通信设备制造信息系统集成服务图文设计制作广告设计、代理广告发布数字内容制作服务不含出版发行数字文化创意软件开发软件销售市场营销策划企业管理咨询信息咨询服务不含许可类信息咨询服务市场调查不含涉外调查工业设计服务玩具销售化妆品零售化妆品批发摄像及视频制作服务平面设计法律咨询不含依法须律师事务所执业许可的业务旅游开发项目策划咨询体育用品及器材批发体育用品及器材零售户外用品销售体育赛事策划体育健康服务组织体育表演活动体育中介代理服务信息技术咨询服务数据处理服务数据处理和存储支持服务大数据服务云计算装备技术服务电子、机械设备维护不含特种设备智能机器人的研发经营范围中的一般经营项目依法自主开展经营活动通过国家企业信用信息公示系统海南向社会公示许可经营项目食品进出口货物进出口技术进出口在线数据处理与交易处理业务经营类电子商务互联网游戏服务第二类增值电信业务互联网信息服务许可经营项目凭许可证件经营",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "信息传输、软件和信息技术服务业-互联网和相关服务",
"candate": "",
"district": "秀英区",
"name": "海南省学宇思网络科技有限公司",
"base": "han",
"apprdate": "2024-09-14"
}
}
]
}
}

View File

@@ -1,646 +0,0 @@
{
"msg": "查询成功",
"code": "0000",
"orderNo": "20241113191941335900073",
"data": {
"total": 8,
"datalist": [
{
"executedPerson": [
{
"caseCode": "2014城中执字第00062号",
"partyCardNum": "45252819740****3016",
"pname": "李强",
"caseCreateTime": "2014-02-11",
"execCourtName": "",
"execMoney": 220605
}
],
"dishonestExecutedPerson": [
{
"businessentity": "",
"areaname": "广西",
"courtname": "柳州市城中区人民法院",
"unperformPart": "",
"type": "0",
"performedPart": "",
"iname": "李强",
"disrupttypename": "其他有履行能力而拒不履行生效法律文书确定义务",
"casecode": "2014城中执字第00062号",
"cardnum": "4525281974****3016",
"performance": "全部未履行",
"regdate": "2014-02-11",
"duty": "中国农业银行股份有限公司柳州城中支行申请执行李强220604.73元",
"gistunit": "柳州市城中区人民法院",
"publishdate": "2014-06-19",
"gistid": "2010城中民二初字第480号民事判决书"
}
],
"orgName": "广西鼎铭房地产开发有限公司",
"pName": "李强",
"stockHolderItem": {
"orgHolderType": "自然人",
"investDate": "",
"investRate": "10.0%",
"subscriptAmt": 100,
"orgHolderName": "李强"
},
"relationship": [
"sh",
"lp",
"tm"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "1000.000000万人民币",
"reccap": 0,
"city": "",
"industry_code": "K",
"industry": "房地产业",
"type": "1",
"nic_code": "K7010",
"staffList": {
"result": [
{
"name": "李强",
"type": "2",
"typeJoin": [
"监事"
]
}
]
},
"legalPersonName": "李强",
"regNumber": "450000200012318",
"creditCode": "91450100742080353R",
"province": "广西壮族自治区",
"regorg": "南宁市市场监督管理局高新技术产业开发区分局",
"companyOrgType": "有限责任公司(自然人投资或控股)",
"revdate": "2016-03-19",
"estiblishTime": "2002-10-16",
"opscope": "房地产开发经营(取得相应资质后方可在其资质等级核定范围内从事房地产开发经营活动);建筑材料、装饰材料、农副土特产品、日用百货、五金交电、汽车零配件的购销;计算机销售及维修。",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "房地产业-房地产业-房地产开发经营-房地产开发经营",
"candate": "",
"district": "",
"name": "广西鼎铭房地产开发有限公司",
"base": "gx",
"apprdate": "2016-03-19"
},
"adminPenalty": [
{
"departmentName": "南宁市工商行政管理局高新技术产业开发区分局",
"reason": "公司成立后无正当理由超过6个月未开业的或者开业后自行停业连续6个月以上",
"punishNumber": "南工商高新处字2016500010024号",
"type": "",
"content": "",
"decisionDate": "2016-03-19",
"legalPersonName": "李强"
},
{
"departmentName": "45011101",
"reason": "南宁恒发网络科技有限公司等3177户企业未依法进行企业信息网上年报公示。经我分局执法人员在以上企业的执照注册住所检查发现上述企业已不在其注册住所经营或办公根据企业注册登记时所留电话也联系不上上述企业。",
"punishNumber": "南工商高新处字2016500010024号",
"type": "吊销执照(登记证)",
"content": "-",
"decisionDate": "2016-03-19",
"legalPersonName": "李强"
}
]
},
{
"executedPerson": [
{
"caseCode": "2010青执字第01000号",
"partyCardNum": "452528********3012",
"pname": "李健",
"caseCreateTime": "2010-09-06",
"execCourtName": "",
"execMoney": 283845
},
{
"caseCode": "2010青执字第00188号",
"partyCardNum": "45252819691****3012",
"pname": "李健",
"caseCreateTime": "2010-02-08",
"execCourtName": "",
"execMoney": 308464
}
],
"orgName": "南宁市铭鼎商贸有限公司",
"pName": "李强",
"stockHolderItem": {
"orgHolderType": "自然人",
"investDate": "",
"investRate": "20.0%",
"subscriptAmt": 20,
"orgHolderName": "李强"
},
"relationship": [
"sh"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "100.000000万人民币",
"reccap": 0,
"city": "南宁市",
"industry_code": "F",
"industry": "零售业",
"type": "1",
"nic_code": "F5211",
"legalPersonName": "李健",
"regNumber": "4501002508737",
"creditCode": "91450107MA5KK3PU6A",
"province": "广西壮族自治区",
"regorg": "南宁市西乡塘区市场监督管理局",
"companyOrgType": "有限责任公司(自然人投资或控股)",
"revdate": "2016-05-28",
"estiblishTime": "2004-07-02",
"opscope": "窗帘布艺,家居用品,装饰材料(危险化学品除外),日用百货,服装,纺织品。",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "批发和零售业-零售业-综合零售-百货零售",
"candate": "",
"district": "",
"name": "南宁市铭鼎商贸有限公司",
"base": "gx",
"apprdate": "2016-05-28"
}
},
{
"executedPerson": [
{
"caseCode": "2014城中执字第00062号",
"partyCardNum": "45252819740****3016",
"pname": "李强",
"caseCreateTime": "2014-02-11",
"execCourtName": "",
"execMoney": 220605
}
],
"dishonestExecutedPerson": [
{
"businessentity": "",
"areaname": "广西",
"courtname": "柳州市城中区人民法院",
"unperformPart": "",
"type": "0",
"performedPart": "",
"iname": "李强",
"disrupttypename": "其他有履行能力而拒不履行生效法律文书确定义务",
"casecode": "2014城中执字第00062号",
"cardnum": "4525281974****3016",
"performance": "全部未履行",
"regdate": "2014-02-11",
"duty": "中国农业银行股份有限公司柳州城中支行申请执行李强220604.73元",
"gistunit": "柳州市城中区人民法院",
"publishdate": "2014-06-19",
"gistid": "2010城中民二初字第480号民事判决书"
}
],
"orgName": "广西鼎铭房地产置换服务有限公司南宁分公司",
"pName": "李强",
"relationship": [
"lp",
"tm",
"his_tm"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "5.0万人民币",
"reccap": 0,
"city": "南宁市",
"industry_code": "K",
"industry": "房地产业",
"type": "1",
"nic_code": "K7030",
"staffList": {
"result": [
{
"name": "李强",
"type": "2",
"typeJoin": [
""
]
}
]
},
"legalPersonName": "李强",
"regNumber": "4501001005198",
"creditCode": "",
"province": "广西壮族自治区",
"his_staffList": {
"result": [
{
"name": "李强",
"type": "2",
"typeJoin": [
""
]
}
]
},
"regorg": "南宁市青秀区市场监督管理局",
"companyOrgType": "有限责任公司分公司(自然人投资或控股)",
"revdate": "2018-06-25",
"estiblishTime": "2002-01-28",
"opscope": "房地产信息咨询服务,房地产交易居间、代理、行纪;商品信息咨询(不含期货、金融、保险、证券等国家专项规定),商品交易居间、代理、行纪。",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "房地产业-房地产业-房地产中介服务-房地产中介服务",
"candate": "",
"district": "青秀区",
"name": "广西鼎铭房地产置换服务有限公司南宁分公司",
"base": "gx",
"apprdate": "2018-06-25"
}
},
{
"executedPerson": [
{
"caseCode": "2014城中执字第00062号",
"partyCardNum": "45252819740****3016",
"pname": "李强",
"caseCreateTime": "2014-02-11",
"execCourtName": "",
"execMoney": 220605
}
],
"dishonestExecutedPerson": [
{
"businessentity": "",
"areaname": "广西",
"courtname": "柳州市城中区人民法院",
"unperformPart": "",
"type": "0",
"performedPart": "",
"iname": "李强",
"disrupttypename": "其他有履行能力而拒不履行生效法律文书确定义务",
"casecode": "2014城中执字第00062号",
"cardnum": "4525281974****3016",
"performance": "全部未履行",
"regdate": "2014-02-11",
"duty": "中国农业银行股份有限公司柳州城中支行申请执行李强220604.73元",
"gistunit": "柳州市城中区人民法院",
"publishdate": "2014-06-19",
"gistid": "2010城中民二初字第480号民事判决书"
}
],
"orgName": "深圳市亿讯时空信息技术有限公司北京分公司",
"pName": "李强",
"relationship": [
"lp",
"tm"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销",
"regCapital": "",
"reccap": 0,
"city": "北京市",
"industry_code": "I",
"industry": "软件和信息技术服务业",
"type": "1",
"nic_code": "I659",
"staffList": {
"result": [
{
"name": "李强",
"type": "2",
"typeJoin": [
"负责人"
]
}
]
},
"legalPersonName": "李强",
"regNumber": "1101081949120",
"creditCode": "91110108MA0464P97H",
"province": "北京市",
"regorg": "北京市工商行政管理局海淀分局",
"companyOrgType": "其他有限责任公司分公司",
"revdate": "2010-11-25",
"estiblishTime": "2006-04-13",
"opscope": "计算机软件和系统集成及辅助设备;网络工程;通讯设备的技术开发、咨询;广告设计。",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "信息传输、软件和信息技术服务业-软件和信息技术服务业-其他信息技术服务业",
"candate": "",
"district": "海淀区",
"name": "深圳市亿讯时空信息技术有限公司北京分公司",
"base": "bj",
"apprdate": "2006-04-13"
},
"adminPenalty": [
{
"departmentName": "海淀分局",
"reason": "",
"punishNumber": "京工商海处字2010第D2389号",
"type": "逾期年检",
"content": "",
"decisionDate": "2010-08-23",
"legalPersonName": "李强"
}
]
},
{
"executedPerson": [
{
"caseCode": "2014城中执字第00062号",
"partyCardNum": "45252819740****3016",
"pname": "李强",
"caseCreateTime": "2014-02-11",
"execCourtName": "",
"execMoney": 220605
},
{
"caseCode": "2010青执字第00198号",
"partyCardNum": "36042819721****0037",
"pname": "秦学文",
"caseCreateTime": "2010-02-08",
"execCourtName": "",
"execMoney": 444028
}
],
"dishonestExecutedPerson": [
{
"businessentity": "",
"areaname": "广西",
"courtname": "柳州市城中区人民法院",
"unperformPart": "",
"type": "0",
"performedPart": "",
"iname": "李强",
"disrupttypename": "其他有履行能力而拒不履行生效法律文书确定义务",
"casecode": "2014城中执字第00062号",
"cardnum": "4525281974****3016",
"performance": "全部未履行",
"regdate": "2014-02-11",
"duty": "中国农业银行股份有限公司柳州城中支行申请执行李强220604.73元",
"gistunit": "柳州市城中区人民法院",
"publishdate": "2014-06-19",
"gistid": "2010城中民二初字第480号民事判决书"
}
],
"orgName": "深圳市亿讯时空信息技术有限公司",
"pName": "李强",
"stockHolderItem": {
"orgHolderType": "自然人",
"investDate": "",
"investRate": "17.0%",
"subscriptAmt": 170,
"orgHolderName": "李强"
},
"relationship": [
"sh",
"tm"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "1000.000000万人民币",
"reccap": 0,
"city": "深圳市",
"industry_code": "M",
"industry": "科技推广和应用服务业",
"type": "1",
"nic_code": "M7590",
"staffList": {
"result": [
{
"name": "李强",
"type": "2",
"typeJoin": [
"董事,总经理"
]
}
]
},
"legalPersonName": "李铭",
"regNumber": "440301103603769",
"creditCode": "91440300786556245H",
"province": "广东省",
"regorg": "福田局",
"companyOrgType": "有限责任公司",
"revdate": "2020-04-07",
"estiblishTime": "2006-03-23",
"opscope": "一般经营项目是:计算机软件和系统集成及辅助设备、网络工程、通讯设备的技术开发、咨询、销售,国内贸易(不含专营、专控、专卖商品),从事货物、技术进出口业务(不含分销、国家专营专控商品);广告业务。,许可经营项目是:",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "科学研究和技术服务业-科技推广和应用服务业-其他科技推广服务业-其他科技推广服务业",
"candate": "2020-04-07",
"district": "福田区",
"name": "深圳市亿讯时空信息技术有限公司",
"base": "gd",
"apprdate": "2008-09-04"
}
},
{
"executedPerson": [
{
"caseCode": "2010青执字第01000号",
"partyCardNum": "452528********3012",
"pname": "李健",
"caseCreateTime": "2010-09-06",
"execCourtName": "",
"execMoney": 283845
},
{
"caseCode": "2010青执字第00188号",
"partyCardNum": "45252819691****3012",
"pname": "李健",
"caseCreateTime": "2010-02-08",
"execCourtName": "",
"execMoney": 308464
}
],
"orgName": "南宁市豆花香食品有限公司",
"pName": "李强",
"stockHolderItem": {
"orgHolderType": "自然人",
"investDate": "2003-08-06",
"investRate": "50.0%",
"subscriptAmt": 25,
"orgHolderName": "李强"
},
"relationship": [
"sh"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "50万元人民币",
"reccap": 0,
"city": "南宁市",
"industry_code": "F",
"industry": "零售业",
"type": "1",
"nic_code": "F5227",
"legalPersonName": "李健",
"regNumber": "4501002505675",
"creditCode": "91450100MA5KJ83P3J",
"province": "广西壮族自治区",
"regorg": "南宁市行政审批局",
"companyOrgType": "有限责任公司(自然人投资或控股)",
"revdate": "2007-02-08",
"estiblishTime": "2003-08-06",
"opscope": "豆制品的生产及销售;农副土特产品,日用百货,五金交电的销售。",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "批发和零售业-零售业-食品、饮料及烟草制品专门零售-烟草制品零售",
"candate": "",
"district": "",
"name": "南宁市豆花香食品有限公司",
"base": "gx",
"apprdate": "2004-06-30"
}
},
{
"executedPerson": [
{
"caseCode": "2010青执字第01000号",
"partyCardNum": "452528********3012",
"pname": "李健",
"caseCreateTime": "2010-09-06",
"execCourtName": "",
"execMoney": 283845
},
{
"caseCode": "2010青执字第00188号",
"partyCardNum": "45252819691****3012",
"pname": "李健",
"caseCreateTime": "2010-02-08",
"execCourtName": "",
"execMoney": 308464
},
{
"caseCode": "2014城中执字第00062号",
"partyCardNum": "45252819740****3016",
"pname": "李强",
"caseCreateTime": "2014-02-11",
"execCourtName": "",
"execMoney": 220605
}
],
"dishonestExecutedPerson": [
{
"businessentity": "",
"areaname": "广西",
"courtname": "柳州市城中区人民法院",
"unperformPart": "",
"type": "0",
"performedPart": "",
"iname": "李强",
"disrupttypename": "其他有履行能力而拒不履行生效法律文书确定义务",
"casecode": "2014城中执字第00062号",
"cardnum": "4525281974****3016",
"performance": "全部未履行",
"regdate": "2014-02-11",
"duty": "中国农业银行股份有限公司柳州城中支行申请执行李强220604.73元",
"gistunit": "柳州市城中区人民法院",
"publishdate": "2014-06-19",
"gistid": "2010城中民二初字第480号民事判决书"
}
],
"orgName": "广西鼎铭房地产置换服务有限公司",
"pName": "李强",
"stockHolderItem": {
"orgHolderType": "自然人",
"investDate": "",
"investRate": "10.87%",
"subscriptAmt": 50,
"orgHolderName": "李强"
},
"relationship": [
"sh",
"tm"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "250万元人民币",
"reccap": 200,
"city": "柳州市",
"industry_code": "I",
"industry": "软件和信息技术服务业",
"type": "1",
"nic_code": "I6513",
"staffList": {
"result": [
{
"name": "李强",
"type": "2",
"typeJoin": [
"监事"
]
}
]
},
"legalPersonName": "李健",
"regNumber": "4502002501968",
"creditCode": "91450200MA5KPNEG3T",
"province": "广西壮族自治区",
"regorg": "柳州市市场监督管理局",
"companyOrgType": "有限责任公司(自然人投资或控股)",
"revdate": "2009-01-04",
"estiblishTime": "2001-04-11",
"opscope": "连锁经营:房地产信息咨询服务,房地产交易居间、代理、行纪;商品信息咨询(不含期货、金融、保险、证券等国家专项规定),商品交易居间、代理、行纪。",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "信息传输、软件和信息技术服务业-软件和信息技术服务业-软件开发-应用软件开发",
"candate": "",
"district": "",
"name": "广西鼎铭房地产置换服务有限公司",
"base": "gx",
"apprdate": "2005-09-26"
}
},
{
"orgName": "广西鼎铭装饰工程有限公司",
"pName": "李强",
"stockHolderItem": {
"orgHolderType": "自然人",
"investDate": "",
"investRate": "5.26%",
"subscriptAmt": 30,
"orgHolderName": "李强"
},
"relationship": [
"sh"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "300万元人民币",
"reccap": 0,
"city": "南宁市",
"industry_code": "E",
"industry": "建筑装饰、装修和其他建筑业",
"type": "1",
"nic_code": "E5011",
"legalPersonName": "李健",
"regNumber": "4500002501464",
"creditCode": "914500007479525012",
"province": "广西壮族自治区",
"regorg": "广西壮族自治区市场监督管理局",
"companyOrgType": "有限责任公司(自然人投资或控股)",
"revdate": "2007-09-14",
"estiblishTime": "2003-02-27",
"opscope": "建筑装修装饰工程专业承包(暂定)叁级;五金交电、日用百货、建筑材料、装饰材料、机电产品、汽车配件、摩托车配件的购销。",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "建筑业-建筑装饰、装修和其他建筑业-建筑装饰和装修业-公共建筑装饰和装修",
"candate": "",
"district": "",
"name": "广西鼎铭装饰工程有限公司",
"base": "gx",
"apprdate": "2005-03-10"
}
}
]
}
}

View File

@@ -1,150 +0,0 @@
{
"msg": "查询成功",
"code": "0000",
"orderNo": "20241113214538120270654",
"data": {
"total": 4,
"datalist": [
{
"orgName": "厦门市湖里区肖山泗建材店",
"pName": "李金桂",
"relationship": [
"lp"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "",
"reccap": 0,
"city": "厦门市",
"industry_code": "F",
"industry": "批发业",
"type": "1",
"nic_code": "F516",
"legalPersonName": "李金桂",
"regNumber": "350206800393889",
"creditCode": "92350206MA3212DY6N",
"province": "福建省",
"regorg": "厦门市湖里区市场监督管理局",
"companyOrgType": "个体",
"revdate": "2024-09-06",
"estiblishTime": "2018-08-21",
"opscope": "",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "批发和零售业-批发业-矿产品、建材及化工产品批发",
"candate": "",
"district": "湖里区",
"name": "厦门市湖里区肖山泗建材店",
"base": "fj",
"apprdate": "2018-08-21"
}
},
{
"orgName": "南安市仑苍巢李水暖配件店",
"pName": "李金桂",
"relationship": [
"lp"
],
"fsource": "1",
"basicInfo": {
"regStatus": "存续(在营、开业、在册)",
"regCapital": "",
"reccap": 0,
"city": "泉州市",
"industry_code": "F",
"industry": "零售业",
"type": "1",
"nic_code": "F5281",
"legalPersonName": "李金桂",
"regNumber": "350583601550067",
"creditCode": "92350583MA34MA8K8Y",
"province": "福建省",
"regorg": "福建省南安市市场监督管理局",
"companyOrgType": "个体",
"revdate": "",
"estiblishTime": "2020-09-08",
"opscope": "",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "批发和零售业-零售业-五金、家具及室内装饰材料专门零售-五金零售",
"candate": "",
"district": "南安市",
"name": "南安市仑苍巢李水暖配件店",
"base": "fj",
"apprdate": "2021-03-22"
}
},
{
"orgName": "厦门市湖里区苑熙照建材店",
"pName": "李金桂",
"relationship": [
"lp"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "",
"reccap": 0,
"city": "厦门市",
"industry_code": "F",
"industry": "零售业",
"type": "1",
"nic_code": "F528",
"legalPersonName": "李金桂",
"regNumber": "350206800392843",
"creditCode": "92350206MA320UEM5W",
"province": "福建省",
"regorg": "厦门市湖里区市场监督管理局",
"companyOrgType": "个体",
"revdate": "2024-09-06",
"estiblishTime": "2018-08-17",
"opscope": "",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "批发和零售业-零售业-五金、家具及室内装饰材料专门零售",
"candate": "",
"district": "湖里区",
"name": "厦门市湖里区苑熙照建材店",
"base": "fj",
"apprdate": "2018-08-17"
}
},
{
"orgName": "厦门市湖里区镜永捷亦服饰店",
"pName": "李金桂",
"relationship": [
"lp"
],
"fsource": "1",
"basicInfo": {
"regStatus": "吊销,未注销",
"regCapital": "",
"reccap": 0,
"city": "厦门市",
"industry_code": "F",
"industry": "零售业",
"type": "1",
"nic_code": "F523",
"legalPersonName": "李金桂",
"regNumber": "350206800389905",
"creditCode": "92350206MA320JJ58B",
"province": "福建省",
"regorg": "厦门市湖里区市场监督管理局",
"companyOrgType": "个体",
"revdate": "2024-09-06",
"estiblishTime": "2018-08-15",
"opscope": "",
"reccapcur": "人民币",
"regCapitalCurrency": "人民币",
"nic_name": "批发和零售业-零售业-纺织、服装及日用品专门零售",
"candate": "",
"district": "湖里区",
"name": "厦门市湖里区镜永捷亦服饰店",
"base": "fj",
"apprdate": "2018-08-15"
}
}
]
}
}

View File

@@ -1,154 +0,0 @@
{
"als_fst_cell_nbank_inteday": "290",
"als_fst_id_nbank_inteday": "138",
"als_lst_cell_nbank_consnum": "1",
"als_lst_cell_nbank_csinteday": "1",
"als_lst_cell_nbank_inteday": "33",
"als_lst_id_nbank_consnum": "1",
"als_lst_id_nbank_csinteday": "1",
"als_lst_id_nbank_inteday": "94",
"als_m12_cell_avg_monnum": "1.20",
"als_m12_cell_caon_allnum": "2",
"als_m12_cell_caon_orgnum": "1",
"als_m12_cell_max_inteday": "128",
"als_m12_cell_max_monnum": "2",
"als_m12_cell_min_inteday": "14",
"als_m12_cell_min_monnum": "0",
"als_m12_cell_nbank_allnum": "6",
"als_m12_cell_nbank_avg_monnum": "1.20",
"als_m12_cell_nbank_ca_allnum": "2",
"als_m12_cell_nbank_ca_orgnum": "1",
"als_m12_cell_nbank_cf_allnum": "4",
"als_m12_cell_nbank_cf_orgnum": "1",
"als_m12_cell_nbank_max_inteday": "128",
"als_m12_cell_nbank_max_monnum": "2",
"als_m12_cell_nbank_min_inteday": "14",
"als_m12_cell_nbank_min_monnum": "0",
"als_m12_cell_nbank_night_allnum": "1",
"als_m12_cell_nbank_night_orgnum": "1",
"als_m12_cell_nbank_orgnum": "2",
"als_m12_cell_nbank_selfnum": "0",
"als_m12_cell_nbank_sloan_allnum": "6",
"als_m12_cell_nbank_sloan_orgnum": "2",
"als_m12_cell_nbank_tot_mons": "5",
"als_m12_cell_nbank_week_allnum": "2",
"als_m12_cell_nbank_week_orgnum": "2",
"als_m12_cell_rel_allnum": "4",
"als_m12_cell_rel_orgnum": "1",
"als_m12_cell_tot_mons": "5",
"als_m12_id_avg_monnum": "1.00",
"als_m12_id_caon_allnum": "2",
"als_m12_id_caon_orgnum": "2",
"als_m12_id_max_inteday": "44",
"als_m12_id_max_monnum": "1",
"als_m12_id_min_inteday": "44",
"als_m12_id_min_monnum": "0",
"als_m12_id_nbank_allnum": "2",
"als_m12_id_nbank_avg_monnum": "1.00",
"als_m12_id_nbank_ca_allnum": "1",
"als_m12_id_nbank_ca_orgnum": "1",
"als_m12_id_nbank_max_inteday": "44",
"als_m12_id_nbank_max_monnum": "1",
"als_m12_id_nbank_min_inteday": "44",
"als_m12_id_nbank_min_monnum": "0",
"als_m12_id_nbank_night_allnum": "0",
"als_m12_id_nbank_night_orgnum": "0",
"als_m12_id_nbank_nsloan_allnum": "1",
"als_m12_id_nbank_nsloan_orgnum": "1",
"als_m12_id_nbank_orgnum": "2",
"als_m12_id_nbank_oth_allnum": "1",
"als_m12_id_nbank_oth_orgnum": "1",
"als_m12_id_nbank_selfnum": "0",
"als_m12_id_nbank_sloan_allnum": "1",
"als_m12_id_nbank_sloan_orgnum": "1",
"als_m12_id_nbank_tot_mons": "2",
"als_m12_id_nbank_week_allnum": "0",
"als_m12_id_nbank_week_orgnum": "0",
"als_m12_id_tot_mons": "2",
"als_m3_cell_avg_monnum": "1.00",
"als_m3_cell_max_inteday": "31",
"als_m3_cell_max_monnum": "1",
"als_m3_cell_min_inteday": "31",
"als_m3_cell_min_monnum": "0",
"als_m3_cell_nbank_allnum": "2",
"als_m3_cell_nbank_avg_monnum": "1.00",
"als_m3_cell_nbank_cf_allnum": "2",
"als_m3_cell_nbank_cf_orgnum": "1",
"als_m3_cell_nbank_max_inteday": "31",
"als_m3_cell_nbank_max_monnum": "1",
"als_m3_cell_nbank_min_inteday": "31",
"als_m3_cell_nbank_min_monnum": "0",
"als_m3_cell_nbank_night_allnum": "1",
"als_m3_cell_nbank_night_orgnum": "1",
"als_m3_cell_nbank_orgnum": "1",
"als_m3_cell_nbank_selfnum": "0",
"als_m3_cell_nbank_sloan_allnum": "2",
"als_m3_cell_nbank_sloan_orgnum": "1",
"als_m3_cell_nbank_tot_mons": "2",
"als_m3_cell_nbank_week_allnum": "1",
"als_m3_cell_nbank_week_orgnum": "1",
"als_m3_cell_rel_allnum": "2",
"als_m3_cell_rel_orgnum": "1",
"als_m3_cell_tot_mons": "2",
"als_m6_cell_avg_monnum": "1.00",
"als_m6_cell_caon_allnum": "2",
"als_m6_cell_caon_orgnum": "1",
"als_m6_cell_max_inteday": "46",
"als_m6_cell_max_monnum": "1",
"als_m6_cell_min_inteday": "31",
"als_m6_cell_min_monnum": "0",
"als_m6_cell_nbank_allnum": "4",
"als_m6_cell_nbank_avg_monnum": "1.00",
"als_m6_cell_nbank_ca_allnum": "2",
"als_m6_cell_nbank_ca_orgnum": "1",
"als_m6_cell_nbank_cf_allnum": "2",
"als_m6_cell_nbank_cf_orgnum": "1",
"als_m6_cell_nbank_max_inteday": "46",
"als_m6_cell_nbank_max_monnum": "1",
"als_m6_cell_nbank_min_inteday": "31",
"als_m6_cell_nbank_min_monnum": "0",
"als_m6_cell_nbank_night_allnum": "1",
"als_m6_cell_nbank_night_orgnum": "1",
"als_m6_cell_nbank_orgnum": "2",
"als_m6_cell_nbank_selfnum": "0",
"als_m6_cell_nbank_sloan_allnum": "4",
"als_m6_cell_nbank_sloan_orgnum": "2",
"als_m6_cell_nbank_tot_mons": "4",
"als_m6_cell_nbank_week_allnum": "2",
"als_m6_cell_nbank_week_orgnum": "2",
"als_m6_cell_rel_allnum": "2",
"als_m6_cell_rel_orgnum": "1",
"als_m6_cell_tot_mons": "4",
"als_m6_id_avg_monnum": "1.00",
"als_m6_id_caon_allnum": "2",
"als_m6_id_caon_orgnum": "2",
"als_m6_id_max_inteday": "44",
"als_m6_id_max_monnum": "1",
"als_m6_id_min_inteday": "44",
"als_m6_id_min_monnum": "0",
"als_m6_id_nbank_allnum": "2",
"als_m6_id_nbank_avg_monnum": "1.00",
"als_m6_id_nbank_ca_allnum": "1",
"als_m6_id_nbank_ca_orgnum": "1",
"als_m6_id_nbank_max_inteday": "44",
"als_m6_id_nbank_max_monnum": "1",
"als_m6_id_nbank_min_inteday": "44",
"als_m6_id_nbank_min_monnum": "0",
"als_m6_id_nbank_night_allnum": "0",
"als_m6_id_nbank_night_orgnum": "0",
"als_m6_id_nbank_nsloan_allnum": "1",
"als_m6_id_nbank_nsloan_orgnum": "1",
"als_m6_id_nbank_orgnum": "2",
"als_m6_id_nbank_oth_allnum": "1",
"als_m6_id_nbank_oth_orgnum": "1",
"als_m6_id_nbank_selfnum": "0",
"als_m6_id_nbank_sloan_allnum": "1",
"als_m6_id_nbank_sloan_orgnum": "1",
"als_m6_id_nbank_tot_mons": "2",
"als_m6_id_nbank_week_allnum": "0",
"als_m6_id_nbank_week_orgnum": "0",
"als_m6_id_tot_mons": "2",
"code": "00",
"flag_applyloanstr": "1",
"flag_datastrategy": "1"
}

View File

@@ -1,133 +0,0 @@
{
"code": "00",
"data": {
"tl_id_t11_nbank_org": "1",
"tl_id_m6_nbank_passnum": "2",
"tl_cell_t2_nbank_lendamt": "10",
"tl_cell_t5_nbank_org": "1",
"tl_id_t5_nbank_num": "1",
"tl_id_t0_nbank_org": "1",
"tl_cell_t9_nbank_num": "1",
"tl_id_t7_nbank_org": "1",
"tl_id_m1_nbank_passlendamt": "5",
"tl_cell_m9_nbank_passnum": "2",
"flag_datastrategy": "1",
"tl_cell_m6_nbank_passorg": "1",
"tl_cell_m1_nbank_passorg": "1",
"tl_id_m12_nbank_passorg": "1",
"tl_id_m3_nbank_passnum": "1",
"DataStrategy": {
"strategy_version": "1.0",
"product_type": "",
"strategy_id": "DTA_BR0008250",
"product_name": "预置_借贷行为验证",
"scene": "lend"
},
"tl_id_t6_nbank_lendamt": "9",
"tl_id_t6_nbank_org": "1",
"tl_cell_m12_nbank_passlendamt": "18",
"tl_cell_m3_nbank_passlendamt": "9",
"tl_cell_t7_nbank_lendamt": "9",
"tl_cell_m12_nbank_passnum": "2",
"tl_cell_t2_nbank_num": "2",
"tl_cell_t6_nbank_org": "1",
"tl_cell_t11_nbank_num": "1",
"tl_id_m3_nbank_passlendamt": "9",
"tl_cell_m6_nbank_passnum": "2",
"tl_id_t7_nbank_lendamt": "9",
"tl_cell_t11_nbank_org": "1",
"tl_id_m3_nbank_passorg": "1",
"tl_cell_t8_nbank_num": "1",
"tl_id_t6_nbank_num": "1",
"tl_cell_m12_nbank_passorg": "1",
"tl_id_t6_nbank_reamt": "3",
"tl_id_t7_nbank_reamt": "3",
"tl_id_t3_nbank_num": "2",
"tl_cell_t8_nbank_lendamt": "9",
"tl_id_t9_nbank_org": "1",
"tl_id_t1_nbank_lendamt": "14",
"tl_cell_t7_nbank_org": "1",
"tl_id_t9_nbank_reamt": "3",
"tl_id_t8_nbank_reamt": "3",
"tl_id_t1_nbank_org": "1",
"tl_cell_t3_nbank_num": "2",
"tl_id_t8_nbank_lendamt": "9",
"tl_cell_t11_nbank_lendamt": "5",
"tl_cell_m3_nbank_passorg": "1",
"tl_id_t0_nbank_num": "2",
"tl_cell_t4_nbank_org": "1",
"tl_cell_t0_nbank_num": "2",
"tl_id_t0_nbank_lendamt": "18",
"tl_cell_t1_nbank_org": "1",
"tl_id_t9_nbank_lendamt": "9",
"tl_cell_t9_nbank_lendamt": "9",
"tl_cell_t0_nbank_lendamt": "18",
"tl_id_t1_nbank_num": "2",
"tl_cell_t0_nbank_reamt": "7",
"tl_cell_t1_nbank_reamt": "7",
"tl_id_t5_nbank_lendamt": "9",
"tl_cell_m3_nbank_passnum": "1",
"tl_id_m6_nbank_passlendamt": "10",
"tl_cell_t6_nbank_lendamt": "9",
"tl_id_m1_nbank_passorg": "1",
"tl_cell_t6_nbank_num": "1",
"tl_id_t8_nbank_num": "1",
"tl_id_t4_nbank_org": "1",
"tl_cell_t1_nbank_lendamt": "14",
"tl_cell_t2_nbank_org": "1",
"tl_cell_t3_nbank_lendamt": "10",
"tl_id_t2_nbank_num": "2",
"tl_cell_t5_nbank_num": "1",
"swift_number": "3034309_20241113153507_46522614A19",
"tl_id_t5_nbank_reamt": "3",
"tl_cell_t7_nbank_reamt": "3",
"tl_cell_t9_nbank_org": "1",
"tl_cell_t9_nbank_reamt": "3",
"tl_id_t4_nbank_reamt": "3",
"tl_id_t3_nbank_reamt": "4",
"tl_cell_t8_nbank_reamt": "3",
"tl_cell_t4_nbank_reamt": "3",
"tl_id_t1_nbank_reamt": "7",
"tl_id_t2_nbank_reamt": "4",
"tl_cell_t5_nbank_reamt": "3",
"tl_cell_t3_nbank_reamt": "4",
"tl_cell_t6_nbank_reamt": "3",
"tl_cell_m9_nbank_passorg": "1",
"tl_cell_t2_nbank_reamt": "4",
"tl_cell_m9_nbank_passlendamt": "10",
"tl_id_m12_nbank_passlendamt": "18",
"tl_id_t9_nbank_num": "1",
"tl_id_m9_nbank_passorg": "1",
"tl_id_t0_nbank_reamt": "7",
"tl_id_t2_nbank_lendamt": "10",
"tl_id_t3_nbank_org": "1",
"tl_cell_t4_nbank_num": "1",
"tl_cell_t3_nbank_org": "1",
"tl_cell_m1_nbank_passnum": "1",
"code": "00",
"tl_id_t2_nbank_org": "1",
"tl_id_m12_nbank_passnum": "2",
"tl_cell_t4_nbank_lendamt": "9",
"tl_id_m9_nbank_passlendamt": "10",
"tl_cell_t0_nbank_org": "1",
"tl_id_m9_nbank_passnum": "2",
"tl_id_t3_nbank_lendamt": "10",
"tl_cell_m1_nbank_passlendamt": "5",
"tl_cell_t1_nbank_num": "2",
"tl_id_m6_nbank_passorg": "1",
"tl_id_t11_nbank_lendamt": "5",
"tl_id_t11_nbank_num": "1",
"tl_cell_t5_nbank_lendamt": "9",
"tl_id_t5_nbank_org": "1",
"tl_id_t4_nbank_lendamt": "9",
"tl_cell_t8_nbank_org": "1",
"tl_id_t7_nbank_num": "1",
"tl_cell_m6_nbank_passlendamt": "10",
"tl_id_t4_nbank_num": "1",
"tl_id_m1_nbank_passnum": "1",
"tl_id_t8_nbank_org": "1",
"tl_cell_t7_nbank_num": "1",
"flag_totalloan": "1"
},
"flag_totalloan": "1"
}

View File

@@ -1,17 +0,0 @@
{
"code": "100002",
"flag_specialList_c": "0",
"data": {
"code": "100002",
"flag_specialList_c": "0",
"swift_number": "3034309_20241113140028_45772614A19",
"flag_datastrategy": "0",
"DataStrategy": {
"strategy_version": "1.0",
"product_type": "100099",
"strategy_id": "DTA_BR0007511",
"product_name": "预置_特殊名单验证",
"scene": "lend"
}
}
}

View File

@@ -0,0 +1,53 @@
# 环境变量配置说明
## 环境变量文件
本项目使用 Vite 的环境变量功能,支持以下环境变量文件:
- `.env`:所有环境都会加载的默认变量
- `.env.development`:开发环境变量(`npm run dev` 时加载)
- `.env.production`:生产环境变量(`npm run build` 时加载)
## 已配置的环境变量
| 变量名 | 说明 | 示例值 |
|--------|------|--------|
| VITE_APP_BASE_URL | API 基础URL | https://www.quannengcha.com |
| VITE_APP_DEBUG | 调试模式 | true/false |
## 在项目中使用环境变量
### 在 Vue 组件中使用
```vue
<script setup>
// 使用 import.meta.env 访问环境变量
const baseUrl = import.meta.env.VITE_APP_BASE_URL
const isDebug = import.meta.env.VITE_APP_DEBUG === 'true'
</script>
```
### 在 JS/TS 文件中使用
```js
// 使用 import.meta.env 访问环境变量
const baseUrl = import.meta.env.VITE_APP_BASE_URL
const isDebug = import.meta.env.VITE_APP_DEBUG === 'true'
// 获取当前环境模式
const mode = import.meta.env.MODE
```
## 获取当前环境
```js
// 获取当前环境模式development、production等
const mode = import.meta.env.MODE
```
## 注意事项
1. 所有环境变量必须以 `VITE_` 开头才能在客户端代码中访问
2. 环境变量默认为字符串类型,需要自行转换为其他类型(如布尔值)
3. 修改环境变量后需要重启开发服务器才能生效
4. 不要在环境变量文件中存储敏感信息如API密钥等

View File

@@ -1,15 +0,0 @@
import uni from '@uni-helper/eslint-config'
export default uni(
{
globals: {
uni: true,
wx: true, // 如果您同时使用了微信小程序的全局变量
},
unocss: true,
rules: {
'no-console': 'off', // 关闭 no-console 规则
'no-unused-vars': 'warn',
},
},
)

View File

@@ -26,6 +26,7 @@ export default defineManifestConfig({
/* 模块配置 */
modules: {
Payment: {},
Share: {},
},
/* 应用发布信息 */
distribute: {
@@ -60,6 +61,19 @@ export default defineManifestConfig({
// #endif
},
// share: {
// weixin: {
// appid: 'wx开头的微信开放平台AppID',
// UniversalLinks: 'https://www.quannengcha.com/app/',
// }
// },
// oauth: {
// weixin: {
// appid: 'wx开头的微信开放平台AppID',
// appsecret: '微信开放平台AppSecret',
// UniversalLinks: 'https://www.quannengcha.com/app/'
// }
// }
},
icons: {
android: {
@@ -124,4 +138,24 @@ export default defineManifestConfig({
enable: false,
},
'vueVersion': '3',
/* UTS 插件配置 */
'uts': {
'plugins': {
'webview': {
'version': '1.0.0',
'description': 'Web视图插件支持在App内打开网页',
'platforms': {
'android': {
'appid': '__UNI_WEBVIEW_ANDROID',
'autostart': false
},
'ios': {
'appid': '__UNI_WEBVIEW_IOS',
'autostart': false
}
}
}
}
}
})

View File

@@ -41,39 +41,43 @@
"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",
"lint": "eslint .",
"lint:fix": "eslint . --fix"
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-4020420240722002",
"@dcloudio/uni-app-plus": "3.0.0-4020420240722002",
"@dcloudio/uni-components": "3.0.0-4020420240722002",
"@dcloudio/uni-h5": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-alipay": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-baidu": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-jd": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-kuaishou": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-lark": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-qq": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-toutiao": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-weixin": "3.0.0-4020420240722002",
"@dcloudio/uni-mp-xhs": "3.0.0-4020420240722002",
"@dcloudio/uni-quickapp-webview": "3.0.0-4020420240722002",
"@dcloudio/uni-app": "3.0.0-4050520250307001",
"@dcloudio/uni-app-harmony": "3.0.0-4050520250307001",
"@dcloudio/uni-app-plus": "3.0.0-4050520250307001",
"@dcloudio/uni-components": "3.0.0-4050520250307001",
"@dcloudio/uni-h5": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-alipay": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-baidu": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-jd": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-lark": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-qq": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-toutiao": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-weixin": "3.0.0-4050520250307001",
"@dcloudio/uni-mp-xhs": "3.0.0-4050520250307001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4050520250307001",
"@rollup/rollup-win32-x64-msvc": "^4.27.4",
"@vant/area-data": "^2.0.0",
"@vueuse/core": "^11.1.0",
"crypto-js": "^4.2.0",
"pinia": "^3.0.1",
"qrcode": "^1.5.4",
"uqrcodejs": "^4.0.7",
"vue": "~3.4.21",
"vue-i18n": "^9.14.1",
"wot-design-uni": "^1.3.12"
},
"devDependencies": {
"@dcloudio/types": "^3.4.12",
"@dcloudio/uni-automator": "3.0.0-4020420240722002",
"@dcloudio/uni-cli-shared": "3.0.0-4020420240722002",
"@dcloudio/uni-stacktracey": "3.0.0-4020420240722002",
"@dcloudio/types": "^3.4.14",
"@dcloudio/uni-automator": "3.0.0-4050520250307001",
"@dcloudio/uni-cli-shared": "3.0.0-4050520250307001",
"@dcloudio/uni-stacktracey": "3.0.0-4050520250307001",
"@dcloudio/uni-uts-v1": "3.0.0-4050520250307001",
"@dcloudio/uni-vue-devtools": "3.0.0-4020420240722002",
"@dcloudio/vite-plugin-uni": "3.0.0-4020420240722002",
"@dcloudio/vite-plugin-uni": "3.0.0-4050520250307001",
"@iconify-json/carbon": "^1.2.3",
"@mini-types/alipay": "^3.0.14",
"@types/node": "^20.16.12",
@@ -89,14 +93,14 @@
"@unocss/eslint-config": "^0.62.4",
"@vue/runtime-core": "^3.5.12",
"@vue/tsconfig": "^0.5.1",
"eslint": "^9.12.0",
"miniprogram-api-typings": "^3.12.3",
"sass": "~1.79.0",
"sass-embedded": "~1.79.0",
"typescript": "~5.5.4",
"unocss": "^0.62.4",
"unplugin-auto-import": "^0.18.3",
"vite": "^5.4.9",
"unplugin-vue-components": "^28.4.1",
"vite": "^5.2.8",
"vue-tsc": "^2.1.6"
}
}

View File

@@ -24,6 +24,11 @@ export default defineUniPages({
text: '',
visible: false,
},
{
pagePath: 'pages/agent',
text: '',
visible: false,
},
{
pagePath: 'pages/ai',
text: '',

1673
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,88 @@
<script setup>
import { onLaunch } from '@dcloudio/uni-app'
import { refreshToken, getUserInfo } from '@/api/apis'
import { getAgentInfo } from '@/apis/agent'
onLaunch(() => {
refreshTokenIfNeeded()
getUser()
getAgentInformation()
})
const refreshTokenIfNeeded = async () => {
const token = uni.getStorageSync("token")
const refreshAfter = uni.getStorageSync("refreshAfter")
const accessExpire = uni.getStorageSync("accessExpire")
const currentTime = new Date().getTime()
// 如果 token 已过期,直接返回
if (accessExpire) {
const accessExpireInMilliseconds = parseInt(accessExpire) * 1000 // 转换为毫秒级
if (currentTime > accessExpireInMilliseconds) {
return
}
}
// 如果没有 token直接返回
if (!token) {
return
}
// 如果有 refreshAfter检查当前时间是否超过 refreshAfter
if (refreshAfter) {
const refreshAfterInMilliseconds = parseInt(refreshAfter) * 1000 // 转换为毫秒级
if (currentTime < refreshAfterInMilliseconds) {
return
}
}
// 如果没有 refreshAfter 或者时间超过 refreshAfter执行刷新 token 的请求
try {
const res = await refreshToken()
if (res.code === 200) {
uni.setStorageSync("token", res.data.accessToken)
uni.setStorageSync("refreshAfter", res.data.refreshAfter)
uni.setStorageSync("accessExpire", res.data.accessExpire)
}
} catch (error) {
console.error('刷新token失败', error)
}
}
const getAgentInformation = async () => {
const token = uni.getStorageSync("token")
if (!token) {
return
}
try {
const res = await getAgentInfo()
if (res.code === 200 && res.data) {
// 将代理信息存入缓存
uni.setStorageSync("agentInfo", {
level: res.data.level,
isAgent: res.data.is_agent, // 判断是否是代理
status: res.data.status, // 获取代理状态 0=待审核1=审核通过2=审核未通过3=未申请
agentID: res.data.agent_id,
mobile: res.data.mobile
})
console.log('代理信息已获取并存入缓存')
}
} catch (error) {
console.error('获取代理信息失败', error)
}
}
const getUser = async () => {
const token = uni.getStorageSync("token")
if (!token) {
return
}
const res = await getUserInfo()
if (res.code === 200) {
console.log(res.data)
uni.setStorageSync("userInfo", res.data.userInfo)
}
}
</script>

View File

@@ -119,3 +119,17 @@ export function iapPaymentCallback(data) {
data,
})
}
export function getAgentRevenue() {
return request({
url: '/agent/revenue',
method: 'GET'
})
}
export function refreshToken() {
return request({
url: '/user/getToken',
method: 'POST',
});
}

138
src/apis/agent.js Normal file
View File

@@ -0,0 +1,138 @@
// 代理相关API
import request from '@/utils/request'
/**
* 获取代理信息
*/
export const getAgentInfo = () => {
return request({
url: '/agent/info',
method: 'GET'
})
}
/**
* 获取代理佣金列表
* @param {Object} params 查询参数 {page, page_size}
*/
export const getAgentCommission = (params) => {
return request({
url: '/agent/commission',
method: 'GET',
params
})
}
/**
* 获取代理奖励列表
* @param {Object} params 查询参数 {page, page_size}
*/
export const getAgentRewards = (params) => {
return request({
url: '/agent/rewards',
method: 'GET',
params
})
}
/**
* 获取代理状态
*/
export const getAgentStatus = () => {
return request({
url: '/agent/status',
method: 'GET'
})
}
/**
* 代理申请
* @param {Object} data 申请数据 {region, mobile, wechat_id, code, ancestor?}
*/
export const applyAgent = (data) => {
return request({
url: '/agent/apply',
method: 'POST',
data
})
}
/**
* 获取代理会员用户配置
* @param {Object} params 查询参数 {product_id}
*/
export const getAgentMembershipUserConfig = (params) => {
return request({
url: '/agent/membership/user_config',
method: 'GET',
params
})
}
/**
* 保存代理会员用户配置
* @param {Object} data 配置数据
*/
export const saveAgentMembershipUserConfig = (data) => {
return request({
url: '/agent/membership/save_user_config',
method: 'POST',
data
})
}
/**
* 获取产品配置
*/
export const getProductConfig = () => {
return request({
url: '/agent/product_config',
method: 'GET'
})
}
/**
* 生成推广链接
* @param {Object} data 推广数据 {product, price}
*/
export const generatePromotionLink = (data) => {
return request({
url: '/agent/generating_link',
method: 'POST',
data
})
}
/**
* 获取代理收益
*/
export const getAgentRevenue = () => {
return request({
url: '/agent/revenue',
method: 'GET'
})
}
/**
* 代理提现
* @param {Object} data 提现数据 {payee_account, amount, payee_name}
*/
export const agentWithdrawal = (data) => {
return request({
url: '/agent/withdrawal',
method: 'POST',
data
})
}
/**
* 获取提现记录
* @param {Object} params 查询参数 {page, page_size}
*/
export const getWithdrawalRecords = (params) => {
return request({
url: '/agent/withdrawal',
method: 'GET',
params
})
}

View File

@@ -3,6 +3,8 @@
}
html {
margin: auto !important;
@apply max-w-lg;
font-size: 4px; // * 方便unocss计算1单位 = 0.25rem = 1px
}
@@ -40,3 +42,9 @@ html.dark {
display: none; /* Chrome, Safari, and Edge */
}
.safe-area-top {
padding-top: env(safe-area-inset-top);
}
.safe-area-bottom {
padding-bottom: env(safe-area-inset-bottom);
}

11
src/auto-imports.d.ts vendored
View File

@@ -11,6 +11,8 @@ declare global {
const aesEncrypt: typeof import('./utils/crypto.js')['aesEncrypt']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const chatCrypto: typeof import('./utils/chatCrypto.js')['default']
const chatEncrypt: typeof import('./utils/chatEncrypt.js')['default']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
@@ -111,6 +113,8 @@ declare global {
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const routerGuard: typeof import('./utils/routerGuard.js')['default']
const setupRouterGuard: typeof import('./utils/routerGuard.js')['setupRouterGuard']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
@@ -247,6 +251,7 @@ declare global {
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRouterGuard: typeof import('./composables/useRouterGuard')['useRouterGuard']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
@@ -283,6 +288,7 @@ declare global {
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUser: typeof import('./composables/useUser.js')['useUser']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
@@ -329,6 +335,8 @@ declare module 'vue' {
readonly aesEncrypt: UnwrapRef<typeof import('./utils/crypto.js')['aesEncrypt']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly chatCrypto: UnwrapRef<typeof import('./utils/chatCrypto.js')['default']>
readonly chatEncrypt: UnwrapRef<typeof import('./utils/chatEncrypt.js')['default']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
@@ -429,6 +437,7 @@ declare module 'vue' {
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly setupRouterGuard: UnwrapRef<typeof import('./utils/routerGuard.js')['setupRouterGuard']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
@@ -480,7 +489,6 @@ declare module 'vue' {
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
readonly useCount: UnwrapRef<typeof import('./composables/useCount')['useCount']>
readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']>
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
@@ -561,7 +569,6 @@ declare module 'vue' {
readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']>
readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']>
readonly usePrevious: UnwrapRef<typeof import('@vueuse/core')['usePrevious']>
readonly useQuery: UnwrapRef<typeof import('./composables/useQuery')['useQuery']>
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>

36
src/components.d.ts vendored
View File

@@ -7,37 +7,11 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
AppFooter: typeof import('./components/AppFooter.vue')['default']
AppLogos: typeof import('./components/AppLogos.vue')['default']
HiCounter: typeof import('./components/HiCounter.vue')['default']
InputEntry: typeof import('./components/InputEntry.vue')['default']
LButtonGroup: typeof import('./components/LButtonGroup.vue')['default']
LExpandCollapse: typeof import('./components/LExpandCollapse.vue')['default']
LTabbar: typeof import('./components/LTabbar.vue')['default']
LTable: typeof import('./components/LTable.vue')['default']
LTitle: typeof import('./components/LTitle.vue')['default']
AgentApplicationForm: typeof import('./components/AgentApplicationForm.vue')['default']
EnvDemo: typeof import('./components/EnvDemo.vue')['default']
PriceInputPopup: typeof import('./components/PriceInputPopup.vue')['default']
PrivacyModel: typeof import('./components/PrivacyModel.vue')['default']
QiunDataChartsQiunDataCharts: typeof import('./components/qiun-data-charts/qiun-data-charts.vue')['default']
QiunErrorQiunError: typeof import('./components/qiun-error/qiun-error.vue')['default']
QiunLoadingLoading1: typeof import('./components/qiun-loading/loading1.vue')['default']
QiunLoadingLoading2: typeof import('./components/qiun-loading/loading2.vue')['default']
QiunLoadingLoading3: typeof import('./components/qiun-loading/loading3.vue')['default']
QiunLoadingLoading4: typeof import('./components/qiun-loading/loading4.vue')['default']
QiunLoadingLoading5: typeof import('./components/qiun-loading/loading5.vue')['default']
QiunLoadingQiunLoading: typeof import('./components/qiun-loading/qiun-loading.vue')['default']
WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default']
WdCell: typeof import('wot-design-uni/components/wd-cell/wd-cell.vue')['default']
WdCheckbox: typeof import('wot-design-uni/components/wd-checkbox/wd-checkbox.vue')['default']
WdDivider: typeof import('wot-design-uni/components/wd-divider/wd-divider.vue')['default']
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
WdImg: typeof import('wot-design-uni/components/wd-img/wd-img.vue')['default']
WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default']
WdLoadmore: typeof import('wot-design-uni/components/wd-loadmore/wd-loadmore.vue')['default']
WdNavbar: typeof import('wot-design-uni/components/wd-navbar/wd-navbar.vue')['default']
WdNoticeBar: typeof import('wot-design-uni/components/wd-notice-bar/wd-notice-bar.vue')['default']
WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default']
WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']
WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default']
QRcode: typeof import('./components/QRcode.vue')['default']
VipBanner: typeof import('./components/VipBanner.vue')['default']
}
}

View File

@@ -0,0 +1,341 @@
<template>
<wd-popup v-model="popupVisible" position="bottom" close-on-click-modal @close="handleClose">
<view class="bg-white rounded-t-lg p-4">
<view class="flex justify-between items-center mb-4">
<text class="text-gray-400" @click="cancel">取消</text>
<text class="text-lg font-medium">申请成为代理</text>
<text class="text-gray-400" @click="cancel">关闭</text>
</view>
<wd-form :model="form" :rules="rules">
<wd-cell-group border>
<!-- 区域选择 -->
<wd-col-picker v-model="region" label="代理区域" label-width="100px" prop="region" placeholder="请选择代理区域"
:columns="columns" :column-change="handleColumnChange" @confirm="handleRegionConfirm"
:display-format="displayFormat" />
<!-- 手机号 -->
<wd-input label="手机号码" label-width="100px" type="number" v-model="form.mobile" prop="mobile"
placeholder="请输入您的手机号" :rules="[
{ required: true, message: '请输入手机号' },
{ required: true, pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号' }
]" />
<!-- 验证码 -->
<wd-input label="验证码" label-width="100px" type="number" v-model="form.code" prop="code" placeholder="请输入验证码"
:rules="[{ required: true, message: '请输入验证码' }]" use-suffix-slot>
<template #suffix>
<button class="verify-btn" :disabled="countdown > 0" @click.stop="sendVerifyCode">
{{ countdown > 0 ? `${countdown}s` : '获取验证码' }}
</button>
</template>
</wd-input>
<!-- 微信号 -->
<wd-input label="微信号" label-width="100px" v-model="form.wechat_id" prop="wechat_id" placeholder="请输入您的微信号"
:rules="[{ required: true, message: '请输入微信号' }]" />
</wd-cell-group>
<!-- 同意条款的复选框 -->
<view class="p-4">
<view class="flex items-start">
<wd-checkbox v-model="isAgreed" size="16px" class="flex-shrink-0 mr-2"></wd-checkbox>
<view class="text-xs text-gray-400 leading-tight">
我已阅读并同意
<text class="text-blue-400" @click.stop="toUserAgreement">用户协议</text>
<text class="text-blue-400" @click.stop="toServiceAgreement">信息技术服务合同</text>
<text class="text-blue-400" @click.stop="toAgentManageAgreement">推广方管理制度协议</text>
<view class="text-xs text-gray-400 mt-1">点击勾选即代表您同意上述法律文书的相关条款并签署上述法律文书</view>
<view class="text-xs text-gray-400 mt-1">手机号未在本平台注册账号则申请后将自动生成账号</view>
</view>
</view>
</view>
<view class="p-4">
<wd-button type="primary" block @click="submitForm">提交申请</wd-button>
<wd-button type="default" block class="mt-2" @click="cancel">取消</wd-button>
</view>
</wd-form>
</view>
</wd-popup>
<wd-toast />
</template>
<script setup>
import { ref, computed, watch, onUnmounted } from 'vue'
import { useColPickerData } from '../hooks/useColPickerData'
import { useToast } from 'wot-design-uni'
import { getCode } from '@/api/apis.js' // 导入getCode API
const props = defineProps({
show: {
type: Boolean,
default: false
},
ancestor: {
type: String,
default: ''
}
})
const region = ref([]) // 存储地区代码数组
const regionText = ref('') // 存储地区文本
const isAgreed = ref(false) // 用户是否同意协议
// 格式化显示文本
const displayFormat = (selectedItems) => {
if (selectedItems.length === 0) return ''
return selectedItems.map(item => item.label).join(' ')
}
const emit = defineEmits(['update:show', 'submit', 'close'])
const form = ref({
mobile: '',
code: '',
wechat_id: ''
})
// 使用wot-design-ui的toast组件
const toast = useToast()
// 不再需要监听region变化触发表单验证
// watch(region, (newVal) => {
// // 当region变化时触发表单验证
// if (formRef.value) {
// formRef.value.validate(['region'])
// }
// })
const popupVisible = ref(false)
const countdown = ref(0)
let timer = null
// 初始化省市区数据
const { colPickerData, findChildrenByCode } = useColPickerData()
const columns = ref([
colPickerData.map((item) => {
return {
value: item.value,
label: item.text
}
})
])
// 表单验证规则 - 仍然保留以供wd-form组件使用
const rules = {
region: [{
required: true,
message: '请选择代理区域',
validator: (value) => {
// 这里直接检查region.value而不是传入的value
if (Array.isArray(region.value) && region.value.length === 3) {
return Promise.resolve()
}
return Promise.reject('请选择完整的省市区')
}
}],
mobile: [
{ required: true, message: '请输入手机号' },
{ required: true, pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号' }
],
code: [{ required: true, message: '请输入验证码' }],
wechat_id: [{ required: true, message: '请输入微信号' }]
}
// 协议跳转函数
const toUserAgreement = () => {
uni.navigateTo({
url: '/pages/agreement?type=user'
})
}
const toServiceAgreement = () => {
uni.navigateTo({
url: '/pages/agreement?type=service'
})
}
const toAgentManageAgreement = () => {
uni.navigateTo({
url: '/pages/agreement?type=manage'
})
}
// 监听show属性变化
watch(() => props.show, (newVal) => {
popupVisible.value = newVal
})
// 监听popupVisible同步回props.show
watch(() => popupVisible.value, (newVal) => {
emit('update:show', newVal)
})
// Popup关闭事件
const handleClose = () => {
emit('close')
}
// 取消按钮
const cancel = () => {
popupVisible.value = false
emit('close')
}
// 处理列变化
const handleColumnChange = ({ selectedItem, resolve, finish }) => {
const children = findChildrenByCode(colPickerData, selectedItem.value)
if (children && children.length) {
resolve(children.map(item => ({
label: item.text,
value: item.value
})))
} else {
finish()
}
}
// 区域选择确认 - 获取选中项的文本值
const handleRegionConfirm = ({ value, selectedItems }) => {
// 存储地区文本
regionText.value = selectedItems.map(item => item.label).join('-')
console.log('地区选择完成', regionText.value)
}
// 判断手机号是否有效
const isPhoneNumberValid = computed(() => {
return /^1[3-9]\d{9}$/.test(form.value.mobile)
})
// 发送验证码
const sendVerifyCode = async () => {
// 验证手机号
if (!form.value.mobile) {
toast.info('请输入手机号')
return
}
if (!isPhoneNumberValid.value) {
toast.info('手机号格式不正确')
return
}
// 发送验证码请求
getCode({
mobile: form.value.mobile,
actionType: 'agentApply',
}).then((res) => {
if (res.code === 200) {
toast.success('验证码已发送')
// 开始倒计时
startCountdown()
} else {
toast.error(res.msg || '发送失败')
}
}).catch((err) => {
toast.error('网络错误')
})
}
// 开始倒计时
const startCountdown = () => {
countdown.value = 60
if (timer) clearInterval(timer)
timer = setInterval(() => {
countdown.value--
if (countdown.value <= 0) {
clearInterval(timer)
timer = null
}
}, 1000)
}
// 组件卸载时清除计时器
onUnmounted(() => {
if (timer) {
clearInterval(timer)
timer = null
}
})
// 提交表单 - 不再使用formRef验证
const submitForm = () => {
try {
// 检查区域是否已选择
if (!Array.isArray(region.value) || region.value.length < 3) {
console.log('区域选择不完整:', region.value)
toast.info('请选择完整的代理区域')
return
}
if (!regionText.value) {
toast.info('请选择代理区域')
return
}
// 检查手机号
if (!form.value.mobile) {
console.log('手机号为空')
toast.info('请输入手机号')
return
}
if (!isPhoneNumberValid.value) {
console.log('手机号格式不正确:', form.value.mobile)
toast.info('手机号格式不正确')
return
}
// 检查验证码
if (!form.value.code) {
console.log('验证码为空')
toast.info('请输入验证码')
return
}
// 检查微信号
if (!form.value.wechat_id) {
console.log('微信号为空')
toast.info('请输入微信号')
return
}
// 检查用户是否同意协议
if (!isAgreed.value) {
toast.info('请阅读并同意相关协议')
return
}
// 所有验证通过,构建表单数据
const formData = {
...form.value,
region: regionText.value,
}
console.log('提交的表单数据:', formData)
// 提交完整数据
emit('submit', formData)
} catch (error) {
console.error('提交表单过程中出现异常:', error)
toast.error('系统错误,请稍后重试')
}
}
</script>
<style scoped>
.verify-btn {
height: 32px;
padding: 0 12px;
background-color: #3b82f6;
color: white;
border-radius: 4px;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
}
.verify-btn[disabled] {
background-color: #a0aec0;
}
</style>

View File

@@ -1,25 +0,0 @@
<script lang="ts" setup>
function handleClickGithub() {
if (window?.open) {
window.open('https://github.com/uni-helper/vitesse-uni-app')
}
else {
uni.showToast({
icon: 'none',
title: '请使用浏览器打开',
})
}
}
</script>
<template>
<view text="xl gray4" m-5 flex items-center justify-center gap-3>
<navigator url="/pages/index" open-type="redirect">
<view i-carbon-campsite />
</navigator>
<view cursor-pointer @click="handleClickGithub">
<view i-carbon:logo-github />
</view>
</view>
</template>

View File

@@ -1,27 +0,0 @@
<template>
<view inline-flex cursor-default text-2xl font-300>
<view
flex
flex-col
items-center
hover-class="drop-shadow-md drop-shadow-color-green5"
>
<image inline-block h-18 w-18 src="/static/logo.svg" />
<text mt--2 text-green5>
uni-helper
</text>
</view>
<view
text="3xl gray4"
m="x-4 y-auto"
i-carbon-add transform transition-all-500 hover:rotate-135
/>
<view flex flex-col hover-class="drop-shadow-md drop-shadow-color-purple5">
<image inline-block h-18 w-18 src="/static/vite.png" />
<text mt--2 text-purple5>
Vite
</text>
</view>
</view>
</template>

View File

@@ -0,0 +1,84 @@
<script setup lang="ts">
// 在Vue组件中访问环境变量
const baseUrl = import.meta.env.VITE_APP_BASE_URL
const isDebug = import.meta.env.VITE_APP_DEBUG === 'true'
// 获取当前环境模式
const mode = import.meta.env.MODE
// 用于测试的方法
function testApiCall() {
// 使用环境变量构建API URL
const apiUrl = `${baseUrl}/api/v1/test`
console.log('请求地址:', apiUrl)
// 这里可以添加实际的API调用
uni.showToast({
title: `环境: ${mode}, API: ${apiUrl}`,
icon: 'none'
})
}
</script>
<template>
<view class="env-demo">
<view class="env-info">
<text class="info-title">环境变量信息</text>
<view class="info-item">
<text class="label">基础URL:</text>
<text class="value">{{ baseUrl }}</text>
</view>
<view class="info-item">
<text class="label">调试模式:</text>
<text class="value">{{ isDebug ? '已开启' : '已关闭' }}</text>
</view>
<view class="info-item">
<text class="label">当前环境:</text>
<text class="value">{{ mode }}</text>
</view>
</view>
<button class="test-btn" @click="testApiCall">测试API调用</button>
</view>
</template>
<style>
.env-demo {
padding: 20px;
}
.env-info {
background-color: #f5f5f5;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
}
.info-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
display: block;
}
.info-item {
display: flex;
margin-bottom: 8px;
}
.label {
font-weight: bold;
margin-right: 10px;
width: 80px;
}
.value {
flex: 1;
word-break: break-all;
}
.test-btn {
background-color: #007aff;
color: #ffffff;
}
</style>

View File

@@ -1,23 +0,0 @@
<script setup lang="ts">
const { count, inc, dec } = useCount()
</script>
<template>
<view inline-flex m="y-3">
<view class="btn" @click="dec()">
<text i-carbon-subtract />
</view>
<view font="mono" w="15" m-auto inline-block>
{{ count }}
</view>
<view class="btn" @click="inc()">
<text i-carbon-add />
</view>
</view>
</template>
<style>
.btn {
--at-apply: w-8 h-8 flex items-center justify-center rounded-full bg-teal-600 text-white cursor-pointer
}
</style>

View File

@@ -1,47 +0,0 @@
<script setup lang="ts">
const name = ref('')
function go() {
if (name.value) {
uni.navigateTo({
url: `/pages/hi?name=${name.value}`,
})
}
}
</script>
<template>
<view>
<view
p="x-4 y-2"
w="250px"
m="t-5 auto"
text="center"
bg="transparent"
border="~ rounded gray-200 dark:gray-700 solid"
outline="none active:none"
box-border
w-full
>
<input
v-model="name"
placeholder="What's your name?"
type="text"
autocomplete="off"
mr-0 w-full
>
</view>
<view>
<button
:disabled="!name"
m="t-3 auto"
m-auto w-120rpx rounded bg-teal-600 px-4 py-1 text-sm text-white
hover-class="bg-teal-700"
@click="go"
>
GO
</button>
</view>
</view>
</template>

View File

@@ -1,87 +0,0 @@
<script setup>
// 接收 type 和 options props 以及 v-model
const props = defineProps({
type: {
type: String,
default: 'purple-pink', // 默认颜色渐变
},
options: {
type: Array,
required: true, // 动态传入选项
},
modelValue: {
type: String,
default: '', // v-model 绑定的值
},
})
const emit = defineEmits(['update:modelValue'])
// 选中内容绑定 v-model
const selected = ref(props.modelValue)
// 监听 v-model 的变化
watch(() => props.modelValue, (newValue) => {
selected.value = newValue
})
// 根据type动态生成分割线的类名
const lineClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-gradient-to-r from-blue-400 via-green-500 to-teal-500'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-400 via-yellow-500 to-yellow-600'
case 'red-purple':
return 'bg-gradient-to-r from-red-500 via-purple-500 to-purple-600'
default:
return 'bg-gradient-to-r from-purple-400 via-pink-500 to-red-500'
}
})
// 计算滑动线的位置和宽度
const slideLineStyle = computed(() => {
const index = props.options.findIndex(option => option.value === selected.value)
const buttonWidth = 100 / props.options.length
return {
width: `${buttonWidth}%`,
transform: `translateX(${index * 100}%)`,
}
})
// 选择选项函数
function selectOption(option) {
selected.value = option.value
// 触发 v-model 的更新
emit('update:modelValue', option.value)
}
</script>
<template>
<div class="relative flex">
<div
v-for="(option, index) in options"
:key="index"
class="flex-1 shrink-0 cursor-pointer py-2 text-center text-size-sm font-bold transition-transform duration-200 ease-in-out"
:class="{ 'text-gray-900': selected === option.value, 'text-gray-500': selected !== option.value }"
@click="selectOption(option)"
>
{{ option.label }}
</div>
<div
class="absolute bottom-0 h-[3px] rounded transition-all duration-300"
:style="slideLineStyle"
:class="lineClass"
/>
</div>
</template>
<style scoped>
/* 自定义样式 */
button {
outline: none;
border: none;
cursor: pointer;
}
button:focus {
outline: none;
}
</style>

View File

@@ -1,61 +0,0 @@
<script setup>
import { computed, ref, useSlots } from 'vue'
// 接收最大长度的 prop默认值 100
const props = defineProps({
maxLength: {
type: Number,
default: 100,
},
})
// 记录当前是否展开
const isExpanded = ref(false)
// 获取 slot 内容
const slots = useSlots()
// 计算截断后的内容
const truncatedContent = computed(() => {
const slotContent = getSlotContent()
return slotContent.length > props.maxLength
? `${slotContent.slice(0, props.maxLength)}...`
: slotContent
})
// 获取 slot 内容,确保返回的内容为字符串
function getSlotContent() {
const slotVNode = slots.default ? slots.default()[0] : null
return slotVNode ? slotVNode.children.toString().trim() : '' // 获取并转化为字符串
}
// 切换展开/收起状态
function toggleExpand() {
isExpanded.value = !isExpanded.value
}
</script>
<template>
<view>
<!-- 展开/收起按钮 -->
<!-- 展开/收起的内容 -->
<text v-if="isExpanded">
<slot /> <!-- 使用 slot 来展示传递的内容 -->
</text>
<text v-else>
<text>{{ truncatedContent }}</text>
</text>
<text
:title="isExpanded ? '点击收起' : '点击展开'"
class="cursor-pointer text-blue-500"
@click="toggleExpand"
>
{{ isExpanded ? '收起' : '展开' }}
</text>
</view>
</template>
<style scoped>
</style>

View File

@@ -1,30 +0,0 @@
<script setup>
const tabbar = ref('index')
const menu = reactive([{ title: '首页', icon: 'home', name: 'index' }, { title: 'AI律师', icon: 'chat', name: 'ai' }, { title: '我的', icon: 'user', name: 'me' }])
function tabChange({ value }) {
uni.switchTab({
url: `/pages/${value}`,
})
}
onShow(() => {
const currentPage = getCurrentPages()[getCurrentPages().length - 1].route
const pageName = currentPage.split('/').pop()
tabbar.value = pageName
})
onMounted(() => {
uni.hideTabBar()
})
</script>
<template>
<wd-tabbar v-model="tabbar" custom-class="qnc-tabbar" shape="round" safe-area-inset-bottom fixed @change="tabChange">
<wd-tabbar-item v-for="(item, index) in menu" :key="index" :name="item.name" :title="item.title" :icon="item.icon" />
</wd-tabbar>
</template>
<style scoped>
:deep(.qnc-tabbar) {
bottom: 16px !important;
}
</style>

View File

@@ -1,98 +0,0 @@
<script setup>
import { computed } from 'vue'
// 接收表格数据和类型的 props
const props = defineProps({
data: {
type: Array,
required: true,
},
type: {
type: String,
default: 'purple-pink', // 默认渐变颜色
},
})
// 根据 type 设置不同的渐变颜色(偶数行)
const evenClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-teal-100/40'
// return 'bg-gradient-to-r from-blue-50 via-green-50 to-teal-50'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-50 via-yellow-50 to-yellow-100'
case 'red-purple':
return 'bg-gradient-to-r from-red-50 via-purple-50 to-purple-100'
default:
return 'bg-gradient-to-r from-purple-50 via-pink-50 to-red-50'
}
})
// 动态计算表头的背景颜色和文本颜色
const headerClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-teal-200'
// return 'bg-gradient-to-r from-blue-200 via-green-200 to-teal-200'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-200 via-yellow-200 to-yellow-200'
case 'red-purple':
return 'bg-gradient-to-r from-red-200 via-purple-200 to-purple-200'
default:
return 'bg-gradient-to-r from-purple-200 via-pink-200 to-red-200'
}
})
// 斑马纹样式,偶数行带颜色,奇数行没有颜色,且从第二行开始
function zebraClass(index) {
return index % 2 === 1 ? evenClass.value : ''
}
</script>
<template>
<div class="l-table overflow-x-auto">
<table class="min-w-full border-collapse table-auto text-center text-size-xs">
<thead :class="headerClass">
<tr>
<!-- 插槽渲染表头 -->
<slot name="header" />
</tr>
</thead>
<tbody>
<tr
v-for="(row, index) in data"
:key="index"
:class="zebraClass(index)"
class="border-t"
>
<!-- 插槽渲染每一列的内容 -->
<slot :row="row" />
</tr>
</tbody>
</table>
</div>
</template>
<style scoped>
/* 基础表格样式 */
th {
font-weight: bold;
padding: 12px;
text-align: left;
border: 1px solid #e5e7eb;
}
/* 表格行样式 */
td {
padding: 12px;
border: 1px solid #e5e7eb;
}
table {
width: 100%;
border-spacing: 0;
}
.l-table{
@apply rounded-xl;;
overflow: hidden;
}
</style>

View File

@@ -1,58 +0,0 @@
<script setup>
// 接收 props
const props = defineProps({
title: String,
type: {
type: String,
default: 'purple-pink', // 默认渐变
},
})
// 根据type返回不同的背景类名
const titleClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-gradient-to-r from-blue-400 via-green-500 to-teal-500'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-400 via-yellow-500 to-yellow-600'
case 'red-purple':
return 'bg-gradient-to-r from-red-500 via-purple-500 to-purple-600'
default:
return 'bg-gradient-to-r from-purple-400 via-pink-500 to-red-500'
}
})
// 分割线颜色与背景对应
const lineClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-gradient-to-r from-blue-400 via-green-500 to-teal-500'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-400 via-yellow-500 to-yellow-600'
case 'red-purple':
return 'bg-gradient-to-r from-red-500 via-purple-500 to-purple-600'
default:
return 'bg-gradient-to-r from-purple-400 via-pink-500 to-red-500'
}
})
</script>
<template>
<div class="relative">
<!-- 标题部分 -->
<div :class="titleClass" class="inline-block rounded-lg px-2 py-1 text-white font-bold shadow-md">
{{ title }}
</div>
<!-- 左上角修饰 -->
<div class="absolute left-0 top-0 h-4 w-4 transform rounded-full bg-white shadow-md -translate-x-2 -translate-y-2" />
<!-- 分割线 -->
<div class="relative mt-1.5">
<div :class="lineClass" class="h-[2px] w-full rounded" />
</div>
</div>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,179 @@
<template>
<wd-popup v-model="show" position="bottom" round close-on-click-modal destroy-on-close>
<div class="min-h-[500px] bg-gray-50 text-gray-600">
<div class="h-10 bg-white flex items-center justify-center font-semibold text-lg">设置客户查询价
</div>
<div class="card m-4">
<div class="flex items-center justify-between">
<div class="text-lg">
客户查询价 ()</div>
</div>
<div class="border-b border-gray-200">
<wd-input v-model="price" type="number" label="¥" label-width="28px" size="large"
:placeholder="`${productConfig.price_range_min} - ${productConfig.price_range_max}`"
@blur="onBlurPrice" custom-class="wd-input" />
</div>
<div class="flex items-center justify-between mt-2">
<div>推广收益为<span class="text-orange-500"> {{ promotionRevenue }} </span></div>
<div>我的成本为<span class="text-orange-500"> {{ costPrice }} </span></div>
</div>
</div>
<div class="card m-4">
<div class="text-lg mb-2">收益与成本说明</div>
<div>推广收益 = 客户查询价 - 我的成本</div>
<div>我的成本 = 提价成本 + 底价成本</div>
<div class="mt-1">提价成本超过平台标准定价部分平台会收取部分成本价</div>
<div class="">设定范围<span class="text-orange-500">{{
productConfig.price_range_min }}</span> - <span class="text-orange-500">{{
productConfig.price_range_max }}</span></div>
</div>
<div class="px-4 pb-4">
<wd-button class="w-full" round type="primary" size="large" @click="onConfirm">确认</wd-button>
</div>
</div>
</wd-popup>
<wd-toast />
</template>
<script setup>
import { ref, computed, watch, toRefs } from 'vue'
import { useToast } from 'wot-design-uni'
const props = defineProps({
defaultPrice: {
type: Number,
required: true
},
productConfig: {
type: Object,
required: true
}
})
const { defaultPrice, productConfig } = toRefs(props)
const emit = defineEmits(["change"])
const show = defineModel("show")
const price = ref(null)
const toast = useToast()
watch(show, () => {
price.value = defaultPrice.value
})
const costPrice = computed(() => {
if (!productConfig.value) return 0.00
// 平台定价成本
let platformPricing = 0
platformPricing += productConfig.value.cost_price
if (price.value > productConfig.value.p_pricing_standard) {
platformPricing += (price.value - productConfig.value.p_pricing_standard) * productConfig.value.p_overpricing_ratio
}
if (productConfig.value.a_pricing_standard > platformPricing && productConfig.value.a_pricing_end > platformPricing && productConfig.value.a_overpricing_ratio > 0) {
if (price.value > productConfig.value.a_pricing_standard) {
if (price.value > productConfig.value.a_pricing_end) {
platformPricing += (productConfig.value.a_pricing_end - productConfig.value.a_pricing_standard) * productConfig.value.a_overpricing_ratio
} else {
platformPricing += (price.value - productConfig.value.a_pricing_standard) * productConfig.value.a_overpricing_ratio
}
}
}
return safeTruncate(platformPricing)
})
const promotionRevenue = computed(() => {
return safeTruncate(price.value - costPrice.value)
});
// 价格校验与修正逻辑
const validatePrice = (currentPrice) => {
const min = productConfig.value.price_range_min;
const max = productConfig.value.price_range_max;
let newPrice = Number(currentPrice);
let message = '';
// 处理无效输入
if (isNaN(newPrice)) {
newPrice = defaultPrice.value;
return { newPrice, message: '输入无效,请输入价格' };
}
// 处理小数位数(兼容科学计数法)
try {
const priceString = newPrice.toString()
const [_, decimalPart = ""] = priceString.split('.');
console.log(priceString, decimalPart)
// 当小数位数超过2位时处理
if (decimalPart.length > 2) {
newPrice = parseFloat(safeTruncate(newPrice));
message = '价格已自动格式化为两位小数';
}
} catch (e) {
console.error('价格格式化异常:', e);
}
// 范围校验(基于可能格式化后的值)
if (newPrice < min) {
message = `价格不能低于 ${min}`;
newPrice = min;
} else if (newPrice > max) {
message = `价格不能高于 ${max}`;
newPrice = max;
}
console.log(newPrice, message)
return { newPrice, message };
}
function safeTruncate(num, decimals = 2) {
if (isNaN(num) || !isFinite(num)) return "0.00";
const factor = 10 ** decimals;
const scaled = Math.trunc(num * factor);
const truncated = scaled / factor;
return truncated.toFixed(decimals);
}
const isManualConfirm = ref(false)
const onConfirm = () => {
if (isManualConfirm.value) return
const { newPrice, message } = validatePrice(price.value)
if (message) {
price.value = newPrice
toast.show(message)
} else {
emit("change", price.value)
show.value = false
}
}
const onBlurPrice = () => {
const { newPrice, message } = validatePrice(price.value)
if (message) {
isManualConfirm.value = true
price.value = newPrice
toast.show(message)
}
setTimeout(() => {
isManualConfirm.value = false
}, 0)
}
</script>
<style lang="scss" scoped>
.wd-input {
display: flex !important;
align-items: center !important;
justify-content: center !important;
:deep(.wd-input__label-inner) {
font-size: 24px !important; /* 增大label字体 */
}
:deep(.wd-input__inner) {
font-size: 24px !important; /* 增大输入框内字体 */
}
:deep(.wd-input) {
height: auto !important; /* 确保高度自适应 */
padding: 8px 0 !important; /* 增加垂直内边距 */
}
}
</style>

View File

@@ -51,11 +51,11 @@ onMounted(() => {
</view>
<view class="modal-message">
感谢您使用全能查APP! 我们非常重视您的隐私保护和个人信息保护在您使用全能查APP前请您仔细阅读充分理解
<text class="link" @click="openPage('/pages/userAgreement')">
<text class="link" @click="openPage('/pages/agreement?type=user')">
用户协议
</text>
<text class="link" @click="openPage('/pages/privacyPolicy')">
<text class="link" @click="openPage('/pages/agreement?type=privacy')">
隐私政策
</text>
的各项条款如果您同意请点击下方按钮开始接受我们的服务

545
src/components/QRcode.vue Normal file
View File

@@ -0,0 +1,545 @@
<template>
<wd-popup v-model="show" position="bottom" round>
<view class="max-h-[calc(100vh-100px)] m-4">
<view class="p-4 flex justify-center">
<!-- 添加最大高度限制容器 -->
<view class="max-h-[70vh] rounded-xl overflow-hidden">
<canvas canvas-id="posterCanvas" id="posterCanvas" class="rounded-xl shadow"
:style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }" ref="posterCanvas"></canvas>
</view>
</view>
<view class="divider">分享到好友</view>
<view class="flex items-center justify-around">
<view class="flex flex-col items-center justify-center" @click="savePoster">
<image src="/static/image/icon_share_img.svg" class="w-10 h-10 rounded-full" />
<view class="text-center mt-1 text-gray-600 text-xs">保存图片</view>
</view>
<!-- <view class="flex flex-col items-center justify-center" @click="shareToWechatFriend">
<image src="/static/image/icon_share_wechat.svg" class="w-10 h-10 rounded-full" />
<view class="text-center mt-1 text-gray-600 text-xs">微信好友</view>
</view>
<view class="flex flex-col items-center justify-center" @click="shareToWechatMoments">
<image src="/static/image/icon_share_friends.svg" class="w-10 h-10 rounded-full" />
<view class="text-center mt-1 text-gray-600 text-xs">微信朋友圈</view>
</view> -->
<view class="flex flex-col items-center justify-center" @click="copyUrl">
<image src="/static/image/icon_share_url.svg" class="w-10 h-10 rounded-full" />
<view class="text-center mt-1 text-gray-600 text-xs">复制链接</view>
</view>
</view>
</view>
</wd-popup>
</template>
<script setup>
import { ref, watch, nextTick, computed, onMounted, toRefs, getCurrentInstance } from 'vue';
import UQRCode from 'uqrcodejs';
const props = defineProps({
linkIdentifier: {
type: String,
required: true,
},
mode: {
type: String,
default: "promote", // 例如 "promote" | "invitation"
},
});
const { linkIdentifier, mode } = toRefs(props);
const posterCanvas = ref(null); // 用于绘制海报的canvas
const posterGenerated = ref(false); // 标记海报是否已经生成过
const show = defineModel('show');
const instance = getCurrentInstance();
// 添加画布尺寸变量 - 降低默认尺寸
const canvasWidth = ref(300); // 画布宽度
const canvasHeight = ref(500); // 画布高度
const url = computed(() => {
// 在uniapp中获取当前站点的基础URL
const baseUrl = import.meta.env.VITE_APP_SHARE_URL || 'https://www.tianyuandata.com';
return mode.value === "promote"
? `${baseUrl}/agent/promotionInquire/`
: `${baseUrl}/agent/invitationAgentApply/`;
});
const qrcodeImage = ref(null);
const loadPosterImage = async () => {
if (mode.value === "promote") {
return '/static/image/tg_qrcode_1.png';
} else {
return '/static/image/yq_qrcode_1.png';
}
};
onMounted(async () => {
// 只在挂载时加载图片路径,但不生成海报
qrcodeImage.value = await loadPosterImage();
});
// 计算适合屏幕的画布尺寸
const calculateCanvasSize = (imgWidth, imgHeight) => {
// 获取系统信息
const sysInfo = uni.getSystemInfoSync();
// 计算可用高度屏幕高度的70%
const maxHeight = sysInfo.windowHeight * 0.6;
// 控制最大宽度屏幕宽度的80%
const maxWidth = sysInfo.windowWidth * 0.8;
// 初始尺寸
let width = 300;
let height = width * (imgHeight / imgWidth);
// 如果高度超出限制,按高度缩放
if (height > maxHeight) {
height = maxHeight;
width = height * (imgWidth / imgHeight);
}
// 如果宽度超出限制,按宽度缩放
if (width > maxWidth) {
width = maxWidth;
height = width * (imgHeight / imgWidth);
}
// 返回最终计算的尺寸
return {
width: Math.floor(width),
height: Math.floor(height)
};
};
// 生成海报并合成二维码
const generatePoster = async () => {
console.log('[DEBUG] generatePoster: 开始生成海报');
// 如果已经生成过海报,就直接返回
if (posterGenerated.value) {
console.log('[DEBUG] generatePoster: 海报已生成,跳过');
return;
}
// 确保 DOM 已经渲染完成
await nextTick();
console.log('[DEBUG] generatePoster: DOM已渲染完成');
try {
// 显示加载提示
uni.showLoading({ title: '生成海报中...' });
console.log('[DEBUG] generatePoster: 在APP环境中执行');
const canvasContext = uni.createCanvasContext('posterCanvas', instance.proxy);
if (!canvasContext) {
throw new Error('创建Canvas上下文失败');
}
console.log('[DEBUG] generatePoster: 创建Canvas上下文成功', !!canvasContext);
// 加载海报图片 - 确保绝对路径
const posterImagePath = mode.value === "promote"
? '/static/image/tg_qrcode_1.png'
: '/static/image/yq_qrcode_1.png';
console.log('[DEBUG] generatePoster: 开始加载海报图片', posterImagePath);
try {
// 加载图片信息
const posterImgInfo = await new Promise((resolve, reject) => {
uni.getImageInfo({
src: posterImagePath,
success: res => {
console.log('[DEBUG] generatePoster: 海报图片加载成功', res);
// 计算适合屏幕的尺寸
const size = calculateCanvasSize(res.width, res.height);
canvasWidth.value = size.width;
canvasHeight.value = size.height;
console.log('[DEBUG] generatePoster: 计算画布尺寸', size);
resolve(res);
},
fail: err => {
console.error('[DEBUG] generatePoster: 海报图片加载失败', err);
reject(err);
}
});
});
// 完全清除画布
canvasContext.clearRect(0, 0, canvasWidth.value, canvasHeight.value);
// 绘制流程 - 多次测试以查找问题
// 先尝试绘制底色确认canvas工作正常
canvasContext.setFillStyle('#ffffff');
canvasContext.fillRect(0, 0, canvasWidth.value, canvasHeight.value);
// 先绘制一次确保底色显示
console.log('[DEBUG] generatePoster: 绘制白色背景');
canvasContext.draw(false, () => {
console.log('[DEBUG] generatePoster: 白色背景绘制完成');
// 第一步完成后,绘制背景图
setTimeout(() => {
console.log('[DEBUG] generatePoster: 开始绘制背景图片', posterImgInfo.path);
canvasContext.drawImage(posterImgInfo.path, 0, 0, canvasWidth.value, canvasHeight.value);
console.log('[DEBUG] generatePoster: 背景图片绘制完成');
canvasContext.draw(true, () => {
console.log('[DEBUG] generatePoster: 背景图绘制完成,准备绘制二维码');
// 背景图绘制完成后,绘制二维码
setTimeout(async () => {
try {
// 计算二维码在海报上的位置和大小 - 使用比例计算
const scaleFactor = canvasWidth.value / posterImgInfo.width;
// 根据海报类型和缩放因子调整二维码尺寸和位置
const qrSize = mode.value === "promote"
? Math.min(Math.floor(300 * scaleFactor), canvasWidth.value * 0.4) // 控制最大尺寸
: Math.min(Math.floor(360 * scaleFactor), canvasWidth.value * 0.4);
// 计算水平位置,确保在画布内
const qrX = mode.value === "promote"
? Math.min(Math.floor(180 * scaleFactor), canvasWidth.value - qrSize)
: Math.min(Math.floor(360 * scaleFactor), canvasWidth.value - qrSize);
// 计算垂直位置,确保在画布底部合适位置
const qrY = mode.value === "promote"
? canvasHeight.value - Math.min(Math.floor(480 * scaleFactor), canvasHeight.value * 0.4)
: canvasHeight.value - Math.min(Math.floor(1370 * scaleFactor), canvasHeight.value * 0.8);
console.log('[DEBUG] generatePoster: 二维码参数', { qrX, qrY, qrSize, mode: mode.value, scaleFactor });
// 3. 使用UQRCode生成二维码并绘制到画布
// 创建uQRCode实例
const qr = new UQRCode();
// 设置二维码内容
qr.data = generalUrl();
// 设置二维码大小
qr.size = qrSize;
// 调用制作二维码方法
qr.make();
// 绘制QR码到指定位置
// 获取绘制模块信息
const drawModules = qr.getDrawModules();
for (const drawModule of drawModules) {
if (drawModule.type === 'tile') {
canvasContext.setFillStyle(drawModule.color);
canvasContext.fillRect(
qrX + drawModule.x,
qrY + drawModule.y,
drawModule.width,
drawModule.height
);
}
}
// 4. 最终绘制,这次保留先前绘制的背景图
canvasContext.draw(true, () => {
console.log('[DEBUG] generatePoster: 画布完整绘制完成');
posterGenerated.value = true;
uni.hideLoading();
});
} catch (error) {
console.error('[DEBUG] generatePoster: 二维码生成异常', error);
uni.hideLoading();
uni.showToast({
title: '生成二维码失败',
icon: 'none'
});
}
}, 300);
});
}, 300);
});
} catch (error) {
console.error('[DEBUG] generatePoster: APP环境图片处理失败', error);
uni.hideLoading();
uni.showToast({
title: '生成海报失败',
icon: 'none'
});
}
} catch (error) {
console.error('[DEBUG] generatePoster: 生成海报发生未捕获异常', error);
uni.hideLoading();
uni.showToast({
title: '生成海报失败',
icon: 'none'
});
}
};
// 监听 show 变化show 为 true 时生成海报
watch(show, (newVal) => {
if (newVal && !posterGenerated.value) {
generatePoster(); // 当弹窗显示且海报未生成时生成海报
}
});
// 保存海报图片
const savePoster = () => {
if (!posterGenerated.value) {
uni.showToast({
title: '海报生成中,请稍后再试',
icon: 'none'
});
return;
}
uni.canvasToTempFilePath({
canvasId: 'posterCanvas',
width: canvasWidth.value,
height: canvasHeight.value,
destWidth: canvasWidth.value * 2, // 输出图片宽度为 canvas 宽度的2倍提高清晰度
destHeight: canvasHeight.value * 2, // 输出图片高度为 canvas 高度的2倍提高清晰度
success: (res) => {
// 保存图片到相册
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
uni.showToast({
title: '保存成功',
icon: 'success'
});
},
fail: (err) => {
console.error('保存失败:', err);
// 如果是用户拒绝授权导致的
if (err.errMsg && err.errMsg.includes('auth deny')) {
uni.showModal({
title: '提示',
content: '需要您授权保存图片到相册',
success: (res) => {
if (res.confirm) {
uni.openSetting();
}
}
});
} else {
uni.showToast({
title: '保存失败',
icon: 'none'
});
}
}
});
},
fail: (err) => {
console.error('Canvas转图片失败:', err);
uni.showToast({
title: '保存失败',
icon: 'none'
});
}
}, instance.proxy);
};
// 分享到微信好友
const shareToWechatFriend = () => {
if (!posterGenerated.value) {
uni.showToast({
title: '海报生成中,请稍后再试',
icon: 'none'
});
return;
}
uni.canvasToTempFilePath({
canvasId: 'posterCanvas',
width: canvasWidth.value,
height: canvasHeight.value,
destWidth: canvasWidth.value * 2,
destHeight: canvasHeight.value * 2,
success: (res) => {
// #ifdef APP-PLUS
shareWithSystem('WXSceneSession', res.tempFilePath);
// #endif
// #ifndef APP-PLUS
uni.showToast({
title: '分享功能仅支持APP',
icon: 'none'
});
// #endif
},
fail: (err) => {
console.error('Canvas转图片失败:', err);
uni.showToast({
title: '分享准备失败',
icon: 'none'
});
}
}, instance.proxy);
};
// 分享到微信朋友圈
const shareToWechatMoments = () => {
if (!posterGenerated.value) {
uni.showToast({
title: '海报生成中,请稍后再试',
icon: 'none'
});
return;
}
uni.canvasToTempFilePath({
canvasId: 'posterCanvas',
width: canvasWidth.value,
height: canvasHeight.value,
destWidth: canvasWidth.value * 2,
destHeight: canvasHeight.value * 2,
success: (res) => {
// #ifdef APP-PLUS
shareWithSystem('WXSceneTimeline', res.tempFilePath);
// #endif
// #ifndef APP-PLUS
uni.showToast({
title: '分享功能仅支持APP',
icon: 'none'
});
// #endif
},
fail: (err) => {
console.error('Canvas转图片失败:', err);
uni.showToast({
title: '分享准备失败',
icon: 'none'
});
}
}, instance.proxy);
};
// 通用的分享处理函数
const shareWithSystem = (scene, tempFilePath) => {
try {
// 判断是否安装微信
plus.share.getServices((services) => {
const wechatService = services.find((s) => s.id === 'weixin');
if (!wechatService) {
uni.showToast({
title: '未检测到微信应用',
icon: 'none'
});
return;
}
// 判断微信是否认证
wechatService.authorize(() => {
const shareOptions = {
provider: 'weixin',
scene: scene, // WXSceneSession或WXSceneTimeline
type: 2, // 图片类型
imageUrl: tempFilePath,
title: mode.value === "promote" ? '推广海报' : '邀请海报',
href: generalUrl(),
success: (res) => {
uni.showToast({
title: '分享成功',
icon: 'success'
});
},
fail: (err) => {
console.error('分享失败:', err);
uni.showToast({
title: '分享失败',
icon: 'none'
});
}
};
wechatService.send(shareOptions, () => {
console.log('分享成功');
}, (err) => {
console.error('分享失败:', err);
});
}, (err) => {
console.error('微信认证失败:', err);
uni.showToast({
title: '微信认证失败',
icon: 'none'
});
});
}, (err) => {
console.error('获取分享服务列表失败:', err);
// 如果获取服务失败,尝试使用系统分享
try {
plus.share.sendWithSystem({
pictures: [tempFilePath]
}, () => {
uni.showToast({
title: '分享成功',
icon: 'success'
});
}, (err) => {
uni.showToast({
title: '分享失败',
icon: 'none'
});
});
} catch (e) {
uni.showToast({
title: '当前设备不支持分享',
icon: 'none'
});
}
});
} catch (error) {
console.error('分享出错:', error);
uni.showToast({
title: '分享失败',
icon: 'none'
});
}
};
const generalUrl = () => {
return url.value + encodeURIComponent(linkIdentifier.value);
};
const copyUrl = () => {
uni.setClipboardData({
data: generalUrl(),
success: () => {
uni.showToast({
title: '链接已复制!',
icon: 'success'
});
}
});
};
</script>
<style lang="scss" scoped>
.divider {
position: relative;
display: flex;
align-items: center;
margin: 16px 0;
color: #969799;
font-size: 14px;
&::before,
&::after {
content: '';
height: 1px;
flex: 1;
background-color: #ebedf0;
}
&::before {
margin-right: 16px;
}
&::after {
margin-left: 16px;
}
}
</style>

View File

@@ -0,0 +1,36 @@
<template>
<view class="card mb-4 relative overflow-hidden" @click="goToVip">
<view class="absolute inset-0 bg-gradient-to-r from-yellow-400 to-yellow-300 opacity-40"></view>
<view class="p-2 relative z-10">
<view class="flex justify-between items-center">
<view>
<view class="text-lg font-bold text-yellow-800">会员专享特权</view>
<view class="text-sm text-yellow-700 mt-1">升级VIP获得更多收益</view>
</view>
<view class="bg-yellow-500 px-3 py-1 rounded-full text-white text-sm shadow-sm">
立即查看
</view>
</view>
</view>
<!-- 装饰元素 -->
<view class="absolute -right-4 -top-4 w-16 h-16 bg-yellow-200 rounded-full opacity-60"></view>
<view class="absolute right-5 -bottom-4 w-12 h-12 bg-yellow-100 rounded-full opacity-40"></view>
</view>
</template>
<script setup>
// 跳转到VIP页面
const goToVip = () => {
uni.navigateTo({
url: '/pages/agentVip'
})
}
</script>
<style scoped>
.card {
border-radius: 12px;
background-color: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
</style>

View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,162 +0,0 @@
<template>
<view class="container loading1">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading1',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading1 {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading1 .shape1 {
-webkit-animation: animation1shape1 0.5s ease 0s infinite alternate;
animation: animation1shape1 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation1shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(16px, 16px);
transform: translate(16px, 16px);
}
}
@keyframes animation1shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(16px, 16px);
transform: translate(16px, 16px);
}
}
.loading1 .shape2 {
-webkit-animation: animation1shape2 0.5s ease 0s infinite alternate;
animation: animation1shape2 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation1shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-16px, 16px);
transform: translate(-16px, 16px);
}
}
@keyframes animation1shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-16px, 16px);
transform: translate(-16px, 16px);
}
}
.loading1 .shape3 {
-webkit-animation: animation1shape3 0.5s ease 0s infinite alternate;
animation: animation1shape3 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation1shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(16px, -16px);
transform: translate(16px, -16px);
}
}
@keyframes animation1shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(16px, -16px);
transform: translate(16px, -16px);
}
}
.loading1 .shape4 {
-webkit-animation: animation1shape4 0.5s ease 0s infinite alternate;
animation: animation1shape4 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation1shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-16px, -16px);
transform: translate(-16px, -16px);
}
}
@keyframes animation1shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-16px, -16px);
transform: translate(-16px, -16px);
}
}
</style>

View File

@@ -1,170 +0,0 @@
<template>
<view class="container loading2">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading2',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading2 {
-webkit-transform: rotate(10deg);
transform: rotate(10deg);
}
.container.loading2 .shape {
border-radius: 5px;
}
.container.loading2{
-webkit-animation: rotation 1s infinite;
animation: rotation 1s infinite;
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading2 .shape1 {
-webkit-animation: animation2shape1 0.5s ease 0s infinite alternate;
animation: animation2shape1 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation2shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(20px, 20px);
transform: translate(20px, 20px);
}
}
@keyframes animation2shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(20px, 20px);
transform: translate(20px, 20px);
}
}
.loading2 .shape2 {
-webkit-animation: animation2shape2 0.5s ease 0s infinite alternate;
animation: animation2shape2 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation2shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-20px, 20px);
transform: translate(-20px, 20px);
}
}
@keyframes animation2shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-20px, 20px);
transform: translate(-20px, 20px);
}
}
.loading2 .shape3 {
-webkit-animation: animation2shape3 0.5s ease 0s infinite alternate;
animation: animation2shape3 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation2shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(20px, -20px);
transform: translate(20px, -20px);
}
}
@keyframes animation2shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(20px, -20px);
transform: translate(20px, -20px);
}
}
.loading2 .shape4 {
-webkit-animation: animation2shape4 0.5s ease 0s infinite alternate;
animation: animation2shape4 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation2shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-20px, -20px);
transform: translate(-20px, -20px);
}
}
@keyframes animation2shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-20px, -20px);
transform: translate(-20px, -20px);
}
}
</style>

View File

@@ -1,173 +0,0 @@
<template>
<view class="container loading3">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading3',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading3 {
-webkit-animation: rotation 1s infinite;
animation: rotation 1s infinite;
}
.container.loading3 .shape1 {
border-top-left-radius: 10px;
}
.container.loading3 .shape2 {
border-top-right-radius: 10px;
}
.container.loading3 .shape3 {
border-bottom-left-radius: 10px;
}
.container.loading3 .shape4 {
border-bottom-right-radius: 10px;
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading3 .shape1 {
-webkit-animation: animation3shape1 0.5s ease 0s infinite alternate;
animation: animation3shape1 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation3shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(5px, 5px);
transform: translate(5px, 5px);
}
}
@keyframes animation3shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(5px, 5px);
transform: translate(5px, 5px);
}
}
.loading3 .shape2 {
-webkit-animation: animation3shape2 0.5s ease 0s infinite alternate;
animation: animation3shape2 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation3shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-5px, 5px);
transform: translate(-5px, 5px);
}
}
@keyframes animation3shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-5px, 5px);
transform: translate(-5px, 5px);
}
}
.loading3 .shape3 {
-webkit-animation: animation3shape3 0.5s ease 0s infinite alternate;
animation: animation3shape3 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation3shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(5px, -5px);
transform: translate(5px, -5px);
}
}
@keyframes animation3shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(5px, -5px);
transform: translate(5px, -5px);
}
}
.loading3 .shape4 {
-webkit-animation: animation3shape4 0.5s ease 0s infinite alternate;
animation: animation3shape4 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation3shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-5px, -5px);
transform: translate(-5px, -5px);
}
}
@keyframes animation3shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-5px, -5px);
transform: translate(-5px, -5px);
}
}
</style>

View File

@@ -1,222 +0,0 @@
<template>
<view class="container loading5">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading5',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading5 .shape {
width: 15px;
height: 15px;
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading5 .shape1 {
animation: animation5shape1 2s ease 0s infinite reverse;
}
@-webkit-keyframes animation5shape1 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, 15px);
transform: translate(0, 15px);
}
50% {
-webkit-transform: translate(15px, 15px);
transform: translate(15px, 15px);
}
75% {
-webkit-transform: translate(15px, 0);
transform: translate(15px, 0);
}
}
@keyframes animation5shape1 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, 15px);
transform: translate(0, 15px);
}
50% {
-webkit-transform: translate(15px, 15px);
transform: translate(15px, 15px);
}
75% {
-webkit-transform: translate(15px, 0);
transform: translate(15px, 0);
}
}
.loading5 .shape2 {
animation: animation5shape2 2s ease 0s infinite reverse;
}
@-webkit-keyframes animation5shape2 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(-15px, 0);
transform: translate(-15px, 0);
}
50% {
-webkit-transform: translate(-15px, 15px);
transform: translate(-15px, 15px);
}
75% {
-webkit-transform: translate(0, 15px);
transform: translate(0, 15px);
}
}
@keyframes animation5shape2 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(-15px, 0);
transform: translate(-15px, 0);
}
50% {
-webkit-transform: translate(-15px, 15px);
transform: translate(-15px, 15px);
}
75% {
-webkit-transform: translate(0, 15px);
transform: translate(0, 15px);
}
}
.loading5 .shape3 {
animation: animation5shape3 2s ease 0s infinite reverse;
}
@-webkit-keyframes animation5shape3 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(15px, 0);
transform: translate(15px, 0);
}
50% {
-webkit-transform: translate(15px, -15px);
transform: translate(15px, -15px);
}
75% {
-webkit-transform: translate(0, -15px);
transform: translate(0, -15px);
}
}
@keyframes animation5shape3 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(15px, 0);
transform: translate(15px, 0);
}
50% {
-webkit-transform: translate(15px, -15px);
transform: translate(15px, -15px);
}
75% {
-webkit-transform: translate(0, -15px);
transform: translate(0, -15px);
}
}
.loading5 .shape4 {
animation: animation5shape4 2s ease 0s infinite reverse;
}
@-webkit-keyframes animation5shape4 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, -15px);
transform: translate(0, -15px);
}
50% {
-webkit-transform: translate(-15px, -15px);
transform: translate(-15px, -15px);
}
75% {
-webkit-transform: translate(-15px, 0);
transform: translate(-15px, 0);
}
}
@keyframes animation5shape4 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, -15px);
transform: translate(0, -15px);
}
50% {
-webkit-transform: translate(-15px, -15px);
transform: translate(-15px, -15px);
}
75% {
-webkit-transform: translate(-15px, 0);
transform: translate(-15px, 0);
}
}
</style>

View File

@@ -1,229 +0,0 @@
<template>
<view class="container loading6">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading6',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading6 {
-webkit-animation: rotation 1s infinite;
animation: rotation 1s infinite;
}
.container.loading6 .shape {
width: 12px;
height: 12px;
border-radius: 2px;
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading6 .shape1 {
-webkit-animation: animation6shape1 2s linear 0s infinite normal;
animation: animation6shape1 2s linear 0s infinite normal;
}
@-webkit-keyframes animation6shape1 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, 18px);
transform: translate(0, 18px);
}
50% {
-webkit-transform: translate(18px, 18px);
transform: translate(18px, 18px);
}
75% {
-webkit-transform: translate(18px, 0);
transform: translate(18px, 0);
}
}
@keyframes animation6shape1 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, 18px);
transform: translate(0, 18px);
}
50% {
-webkit-transform: translate(18px, 18px);
transform: translate(18px, 18px);
}
75% {
-webkit-transform: translate(18px, 0);
transform: translate(18px, 0);
}
}
.loading6 .shape2 {
-webkit-animation: animation6shape2 2s linear 0s infinite normal;
animation: animation6shape2 2s linear 0s infinite normal;
}
@-webkit-keyframes animation6shape2 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(-18px, 0);
transform: translate(-18px, 0);
}
50% {
-webkit-transform: translate(-18px, 18px);
transform: translate(-18px, 18px);
}
75% {
-webkit-transform: translate(0, 18px);
transform: translate(0, 18px);
}
}
@keyframes animation6shape2 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(-18px, 0);
transform: translate(-18px, 0);
}
50% {
-webkit-transform: translate(-18px, 18px);
transform: translate(-18px, 18px);
}
75% {
-webkit-transform: translate(0, 18px);
transform: translate(0, 18px);
}
}
.loading6 .shape3 {
-webkit-animation: animation6shape3 2s linear 0s infinite normal;
animation: animation6shape3 2s linear 0s infinite normal;
}
@-webkit-keyframes animation6shape3 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(18px, 0);
transform: translate(18px, 0);
}
50% {
-webkit-transform: translate(18px, -18px);
transform: translate(18px, -18px);
}
75% {
-webkit-transform: translate(0, -18px);
transform: translate(0, -18px);
}
}
@keyframes animation6shape3 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(18px, 0);
transform: translate(18px, 0);
}
50% {
-webkit-transform: translate(18px, -18px);
transform: translate(18px, -18px);
}
75% {
-webkit-transform: translate(0, -18px);
transform: translate(0, -18px);
}
}
.loading6 .shape4 {
-webkit-animation: animation6shape4 2s linear 0s infinite normal;
animation: animation6shape4 2s linear 0s infinite normal;
}
@-webkit-keyframes animation6shape4 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, -18px);
transform: translate(0, -18px);
}
50% {
-webkit-transform: translate(-18px, -18px);
transform: translate(-18px, -18px);
}
75% {
-webkit-transform: translate(-18px, 0);
transform: translate(-18px, 0);
}
}
@keyframes animation6shape4 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, -18px);
transform: translate(0, -18px);
}
50% {
-webkit-transform: translate(-18px, -18px);
transform: translate(-18px, -18px);
}
75% {
-webkit-transform: translate(-18px, 0);
transform: translate(-18px, 0);
}
}
</style>

View File

@@ -1,36 +0,0 @@
<template>
<view>
<Loading1 v-if="loadingType==1"/>
<Loading2 v-if="loadingType==2"/>
<Loading3 v-if="loadingType==3"/>
<Loading4 v-if="loadingType==4"/>
<Loading5 v-if="loadingType==5"/>
</view>
</template>
<script>
import Loading1 from "./loading1.vue";
import Loading2 from "./loading2.vue";
import Loading3 from "./loading3.vue";
import Loading4 from "./loading4.vue";
import Loading5 from "./loading5.vue";
export default {
components:{Loading1,Loading2,Loading3,Loading4,Loading5},
name: 'qiun-loading',
props: {
loadingType: {
type: Number,
default: 2
},
},
data() {
return {
};
},
}
</script>
<style>
</style>

View File

@@ -1,422 +0,0 @@
/*
* uCharts®
* 高性能跨平台图表库支持H5、APP、小程序微信/支付宝/百度/头条/QQ/360、Vue、Taro等支持canvas的框架平台
* Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
* Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
* 复制使用请保留本段注释,感谢支持开源!
*
* uCharts®官方网站
* https://www.uCharts.cn
*
* 开源地址:
* https://gitee.com/uCharts/uCharts
*
* uni-app插件市场地址
* http://ext.dcloud.net.cn/plugin?id=271
*
*/
// 通用配置项
// 主题颜色配置如每个图表类型需要不同主题请在对应图表类型上更改color属性
const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
const cfe = {
//demotype为自定义图表类型
"type": ["pie", "ring", "rose", "funnel", "line", "column", "area", "radar", "gauge","candle","demotype"],
//增加自定义图表类型如果需要categories请在这里加入您的图表类型例如最后的"demotype"
"categories": ["line", "column", "area", "radar", "gauge", "candle","demotype"],
//instance为实例变量承载属性option为eopts承载属性不要删除
"instance": {},
"option": {},
//下面是自定义format配置因除H5端外的其他端无法通过props传递函数只能通过此属性对应下标的方式来替换
"formatter":{
"tooltipDemo1":function(res){
let result = ''
for (let i in res) {
if (i == 0) {
result += res[i].axisValueLabel + '年销售额'
}
let value = '--'
if (res[i].data !== null) {
value = res[i].data
}
// #ifdef H5
result += '\n' + res[i].seriesName + '' + value + ' 万元'
// #endif
// #ifdef APP-PLUS
result += '<br/>' + res[i].marker + res[i].seriesName + '' + value + ' 万元'
// #endif
}
return result;
},
legendFormat:function(name){
return "自定义图例+"+name;
},
yAxisFormatDemo:function (value, index) {
return value + '元';
},
seriesFormatDemo:function(res){
return res.name + '年' + res.value + '元';
}
},
//这里演示了自定义您的图表类型的option可以随意命名之后在组件上 type="demotype" 后组件会调用这个花括号里的option如果组件上还存在eopts参数会将demotype与eopts中option合并后渲染图表。
"demotype":{
"color": color,
//在这里填写echarts的option即可
},
//下面是自定义配置,请添加项目所需的通用配置
"column": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'axis'
},
"grid": {
"top": 30,
"bottom": 50,
"right": 15,
"left": 40
},
"legend": {
"bottom": 'left',
},
"toolbox": {
"show": false,
},
"xAxis": {
"type": 'category',
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
"boundaryGap": true,
"data": []
},
"yAxis": {
"type": 'value',
"axisTick": {
"show": false,
},
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
},
"seriesTemplate": {
"name": '',
"type": 'bar',
"data": [],
"barwidth": 20,
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
},
},
"line": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'axis'
},
"grid": {
"top": 30,
"bottom": 50,
"right": 15,
"left": 40
},
"legend": {
"bottom": 'left',
},
"toolbox": {
"show": false,
},
"xAxis": {
"type": 'category',
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
"boundaryGap": true,
"data": []
},
"yAxis": {
"type": 'value',
"axisTick": {
"show": false,
},
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
},
"seriesTemplate": {
"name": '',
"type": 'line',
"data": [],
"barwidth": 20,
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
},
},
"area": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'axis'
},
"grid": {
"top": 30,
"bottom": 50,
"right": 15,
"left": 40
},
"legend": {
"bottom": 'left',
},
"toolbox": {
"show": false,
},
"xAxis": {
"type": 'category',
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
"boundaryGap": true,
"data": []
},
"yAxis": {
"type": 'value',
"axisTick": {
"show": false,
},
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
},
"seriesTemplate": {
"name": '',
"type": 'line',
"data": [],
"areaStyle": {},
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
},
},
"pie": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'item'
},
"grid": {
"top": 40,
"bottom": 30,
"right": 15,
"left": 15
},
"legend": {
"bottom": 'left',
},
"seriesTemplate": {
"name": '',
"type": 'pie',
"data": [],
"radius": '50%',
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
},
},
"ring": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'item'
},
"grid": {
"top": 40,
"bottom": 30,
"right": 15,
"left": 15
},
"legend": {
"bottom": 'left',
},
"seriesTemplate": {
"name": '',
"type": 'pie',
"data": [],
"radius": ['40%', '70%'],
"avoidLabelOverlap": false,
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
"labelLine": {
"show": true
},
},
},
"rose": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'item'
},
"legend": {
"top": 'bottom'
},
"seriesTemplate": {
"name": '',
"type": 'pie',
"data": [],
"radius": "55%",
"center": ['50%', '50%'],
"roseType": 'area',
},
},
"funnel": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'item',
"formatter": "{b} : {c}%"
},
"legend": {
"top": 'bottom'
},
"seriesTemplate": {
"name": '',
"type": 'funnel',
"left": '10%',
"top": 60,
"bottom": 60,
"width": '80%',
"min": 0,
"max": 100,
"minSize": '0%',
"maxSize": '100%',
"sort": 'descending',
"gap": 2,
"label": {
"show": true,
"position": 'inside'
},
"labelLine": {
"length": 10,
"lineStyle": {
"width": 1,
"type": 'solid'
}
},
"itemStyle": {
"bordercolor": '#fff',
"borderwidth": 1
},
"emphasis": {
"label": {
"fontSize": 20
}
},
"data": [],
},
},
"gauge": {
"color": color,
"tooltip": {
"formatter": '{a} <br/>{b} : {c}%'
},
"seriesTemplate": {
"name": '业务指标',
"type": 'gauge',
"detail": {"formatter": '{value}%'},
"data": [{"value": 50, "name": '完成率'}]
},
},
"candle": {
"xAxis": {
"data": []
},
"yAxis": {},
"color": color,
"title": {
"text": ''
},
"dataZoom": [{
"type": 'inside',
"xAxisIndex": [0, 1],
"start": 10,
"end": 100
},
{
"show": true,
"xAxisIndex": [0, 1],
"type": 'slider',
"bottom": 10,
"start": 10,
"end": 100
}
],
"seriesTemplate": {
"name": '',
"type": 'k',
"data": [],
},
}
}
export default cfe;

View File

@@ -1,606 +0,0 @@
/*
* uCharts®
* 高性能跨平台图表库支持H5、APP、小程序微信/支付宝/百度/头条/QQ/360、Vue、Taro等支持canvas的框架平台
* Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
* Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
* 复制使用请保留本段注释,感谢支持开源!
*
* uCharts®官方网站
* https://www.uCharts.cn
*
* 开源地址:
* https://gitee.com/uCharts/uCharts
*
* uni-app插件市场地址
* http://ext.dcloud.net.cn/plugin?id=271
*
*/
// 主题颜色配置如每个图表类型需要不同主题请在对应图表类型上更改color属性
const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
//事件转换函数主要用作格式化x轴为时间轴根据需求自行修改
const formatDateTime = (timeStamp, returnType)=>{
var date = new Date();
date.setTime(timeStamp * 1000);
var y = date.getFullYear();
var m = date.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
var d = date.getDate();
d = d < 10 ? ('0' + d) : d;
var h = date.getHours();
h = h < 10 ? ('0' + h) : h;
var minute = date.getMinutes();
var second = date.getSeconds();
minute = minute < 10 ? ('0' + minute) : minute;
second = second < 10 ? ('0' + second) : second;
if(returnType == 'full'){return y + '-' + m + '-' + d + ' '+ h +':' + minute + ':' + second;}
if(returnType == 'y-m-d'){return y + '-' + m + '-' + d;}
if(returnType == 'h:m'){return h +':' + minute;}
if(returnType == 'h:m:s'){return h +':' + minute +':' + second;}
return [y, m, d, h, minute, second];
}
const cfu = {
//demotype为自定义图表类型一般不需要自定义图表类型只需要改根节点上对应的类型即可
"type":["pie","ring","rose","word","funnel","map","arcbar","line","column","mount","bar","area","radar","gauge","candle","mix","tline","tarea","scatter","bubble","demotype"],
"range":["饼状图","圆环图","玫瑰图","词云图","漏斗图","地图","圆弧进度条","折线图","柱状图","山峰图","条状图","区域图","雷达图","仪表盘","K线图","混合图","时间轴折线","时间轴区域","散点图","气泡图","自定义类型"],
//增加自定义图表类型如果需要categories请在这里加入您的图表类型例如最后的"demotype"
//自定义类型时需要注意"tline","tarea","scatter","bubble"等时间轴矢量x轴类图表没有categories不需要加入categories
"categories":["line","column","mount","bar","area","radar","gauge","candle","mix","demotype"],
//instance为实例变量承载属性不要删除
"instance":{},
//option为opts及eopts承载属性不要删除
"option":{},
//下面是自定义format配置因除H5端外的其他端无法通过props传递函数只能通过此属性对应下标的方式来替换
"formatter":{
"yAxisDemo1":function(val, index, opts){return val+'元'},
"yAxisDemo2":function(val, index, opts){return val.toFixed(2)},
"xAxisDemo1":function(val, index, opts){return val+'年';},
"xAxisDemo2":function(val, index, opts){return formatDateTime(val,'h:m')},
"seriesDemo1":function(val, index, series, opts){return val+'元'},
"tooltipDemo1":function(item, category, index, opts){
if(index==0){
return '随便用'+item.data+'年'
}else{
return '其他我没改'+item.data+'天'
}
},
"pieDemo":function(val, index, series, opts){
if(index !== undefined){
return series[index].name+''+series[index].data+'元'
}
},
},
//这里演示了自定义您的图表类型的option可以随意命名之后在组件上 type="demotype" 后组件会调用这个花括号里的option如果组件上还存在opts参数会将demotype与opts中option合并后渲染图表。
"demotype":{
//我这里把曲线图当做了自定义图表类型,您可以根据需要随意指定类型或配置
"type": "line",
"color": color,
"padding": [15,10,0,15],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
},
"legend": {
},
"extra": {
"line": {
"type": "curve",
"width": 2
},
}
},
//下面是自定义配置,请添加项目所需的通用配置
"pie":{
"type": "pie",
"color": color,
"padding": [5,5,5,5],
"extra": {
"pie": {
"activeOpacity": 0.5,
"activeRadius": 10,
"offsetAngle": 0,
"labelWidth": 15,
"border": true,
"borderWidth": 3,
"borderColor": "#FFFFFF"
},
}
},
"ring":{
"type": "ring",
"color": color,
"padding": [5,5,5,5],
"rotate": false,
"dataLabel": true,
"legend": {
"show": true,
"position": "right",
"lineHeight": 25,
},
"title": {
"name": "收益率",
"fontSize": 15,
"color": "#666666"
},
"subtitle": {
"name": "70%",
"fontSize": 25,
"color": "#7cb5ec"
},
"extra": {
"ring": {
"ringWidth":30,
"activeOpacity": 0.5,
"activeRadius": 10,
"offsetAngle": 0,
"labelWidth": 15,
"border": true,
"borderWidth": 3,
"borderColor": "#FFFFFF"
},
},
},
"rose":{
"type": "rose",
"color": color,
"padding": [5,5,5,5],
"legend": {
"show": true,
"position": "left",
"lineHeight": 25,
},
"extra": {
"rose": {
"type": "area",
"minRadius": 50,
"activeOpacity": 0.5,
"activeRadius": 10,
"offsetAngle": 0,
"labelWidth": 15,
"border": false,
"borderWidth": 2,
"borderColor": "#FFFFFF"
},
}
},
"word":{
"type": "word",
"color": color,
"extra": {
"word": {
"type": "normal",
"autoColors": false
}
}
},
"funnel":{
"type": "funnel",
"color": color,
"padding": [15,15,0,15],
"extra": {
"funnel": {
"activeOpacity": 0.3,
"activeWidth": 10,
"border": true,
"borderWidth": 2,
"borderColor": "#FFFFFF",
"fillOpacity": 1,
"labelAlign": "right"
},
}
},
"map":{
"type": "map",
"color": color,
"padding": [0,0,0,0],
"dataLabel": true,
"extra": {
"map": {
"border": true,
"borderWidth": 1,
"borderColor": "#666666",
"fillOpacity": 0.6,
"activeBorderColor": "#F04864",
"activeFillColor": "#FACC14",
"activeFillOpacity": 1
},
}
},
"arcbar":{
"type": "arcbar",
"color": color,
"title": {
"name": "百分比",
"fontSize": 25,
"color": "#00FF00"
},
"subtitle": {
"name": "默认标题",
"fontSize": 15,
"color": "#666666"
},
"extra": {
"arcbar": {
"type": "default",
"width": 12,
"backgroundColor": "#E9E9E9",
"startAngle": 0.75,
"endAngle": 0.25,
"gap": 2
}
}
},
"line":{
"type": "line",
"color": color,
"padding": [15,10,0,15],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
},
"legend": {
},
"extra": {
"line": {
"type": "straight",
"width": 2,
"activeType": "hollow"
},
}
},
"tline":{
"type": "line",
"color": color,
"padding": [15,10,0,15],
"xAxis": {
"disableGrid": false,
"boundaryGap":"justify",
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
"data":[
{
"min":0,
"max":80
}
]
},
"legend": {
},
"extra": {
"line": {
"type": "curve",
"width": 2,
"activeType": "hollow"
},
}
},
"tarea":{
"type": "area",
"color": color,
"padding": [15,10,0,15],
"xAxis": {
"disableGrid": true,
"boundaryGap":"justify",
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
"data":[
{
"min":0,
"max":80
}
]
},
"legend": {
},
"extra": {
"area": {
"type": "curve",
"opacity": 0.2,
"addLine": true,
"width": 2,
"gradient": true,
"activeType": "hollow"
},
}
},
"column":{
"type": "column",
"color": color,
"padding": [15,15,0,5],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"data":[{"min":0}]
},
"legend": {
},
"extra": {
"column": {
"type": "group",
"width": 30,
"activeBgColor": "#000000",
"activeBgOpacity": 0.08
},
}
},
"mount":{
"type": "mount",
"color": color,
"padding": [15,15,0,5],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"data":[{"min":0}]
},
"legend": {
},
"extra": {
"mount": {
"type": "mount",
"widthRatio": 1.5,
},
}
},
"bar":{
"type": "bar",
"color": color,
"padding": [15,30,0,5],
"xAxis": {
"boundaryGap":"justify",
"disableGrid":false,
"min":0,
"axisLine":false
},
"yAxis": {
},
"legend": {
},
"extra": {
"bar": {
"type": "group",
"width": 30,
"meterBorde": 1,
"meterFillColor": "#FFFFFF",
"activeBgColor": "#000000",
"activeBgOpacity": 0.08
},
}
},
"area":{
"type": "area",
"color": color,
"padding": [15,15,0,15],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
},
"legend": {
},
"extra": {
"area": {
"type": "straight",
"opacity": 0.2,
"addLine": true,
"width": 2,
"gradient": false,
"activeType": "hollow"
},
}
},
"radar":{
"type": "radar",
"color": color,
"padding": [5,5,5,5],
"dataLabel": false,
"legend": {
"show": true,
"position": "right",
"lineHeight": 25,
},
"extra": {
"radar": {
"gridType": "radar",
"gridColor": "#CCCCCC",
"gridCount": 3,
"opacity": 0.2,
"max": 200,
"labelShow": true
},
}
},
"gauge":{
"type": "gauge",
"color": color,
"title": {
"name": "66Km/H",
"fontSize": 25,
"color": "#2fc25b",
"offsetY": 50
},
"subtitle": {
"name": "实时速度",
"fontSize": 15,
"color": "#1890ff",
"offsetY": -50
},
"extra": {
"gauge": {
"type": "default",
"width": 30,
"labelColor": "#666666",
"startAngle": 0.75,
"endAngle": 0.25,
"startNumber": 0,
"endNumber": 100,
"labelFormat": "",
"splitLine": {
"fixRadius": 0,
"splitNumber": 10,
"width": 30,
"color": "#FFFFFF",
"childNumber": 5,
"childWidth": 12
},
"pointer": {
"width": 24,
"color": "auto"
}
}
}
},
"candle":{
"type": "candle",
"color": color,
"padding": [15,15,0,15],
"enableScroll": true,
"enableMarkLine": true,
"dataLabel": false,
"xAxis": {
"labelCount": 4,
"itemCount": 40,
"disableGrid": true,
"gridColor": "#CCCCCC",
"gridType": "solid",
"dashLength": 4,
"scrollShow": true,
"scrollAlign": "left",
"scrollColor": "#A6A6A6",
"scrollBackgroundColor": "#EFEBEF"
},
"yAxis": {
},
"legend": {
},
"extra": {
"candle": {
"color": {
"upLine": "#f04864",
"upFill": "#f04864",
"downLine": "#2fc25b",
"downFill": "#2fc25b"
},
"average": {
"show": true,
"name": ["MA5","MA10","MA30"],
"day": [5,10,20],
"color": ["#1890ff","#2fc25b","#facc14"]
}
},
"markLine": {
"type": "dash",
"dashLength": 5,
"data": [
{
"value": 2150,
"lineColor": "#f04864",
"showLabel": true
},
{
"value": 2350,
"lineColor": "#f04864",
"showLabel": true
}
]
}
}
},
"mix":{
"type": "mix",
"color": color,
"padding": [15,15,0,15],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"disabled": false,
"disableGrid": false,
"splitNumber": 5,
"gridType": "dash",
"dashLength": 4,
"gridColor": "#CCCCCC",
"padding": 10,
"showTitle": true,
"data": []
},
"legend": {
},
"extra": {
"mix": {
"column": {
"width": 20
}
},
}
},
"scatter":{
"type": "scatter",
"color":color,
"padding":[15,15,0,15],
"dataLabel":false,
"xAxis": {
"disableGrid": false,
"gridType":"dash",
"splitNumber":5,
"boundaryGap":"justify",
"min":0
},
"yAxis": {
"disableGrid": false,
"gridType":"dash",
},
"legend": {
},
"extra": {
"scatter": {
},
}
},
"bubble":{
"type": "bubble",
"color":color,
"padding":[15,15,0,15],
"xAxis": {
"disableGrid": false,
"gridType":"dash",
"splitNumber":5,
"boundaryGap":"justify",
"min":0,
"max":250
},
"yAxis": {
"disableGrid": false,
"gridType":"dash",
"data":[{
"min":0,
"max":150
}]
},
"legend": {
},
"extra": {
"bubble": {
"border":2,
"opacity": 0.5,
},
}
}
}
export default cfu;

View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,5 +0,0 @@
# uCharts JSSDK说明
1、如不使用uCharts组件可直接引用u-charts.js打包编译后会`自动压缩`,压缩后体积约为`120kb`
2、如果120kb的体积仍需压缩请手到uCharts官网通过在线定制选择您需要的图表。
3、config-ucharts.js为uCharts组件的用户配置文件升级前请`自行备份config-ucharts.js`文件,以免被强制覆盖。
4、config-echarts.js为ECharts组件的用户配置文件升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

View File

@@ -1,16 +0,0 @@
export function useCount() {
const count = ref(Math.round(Math.random() * 20))
function inc() {
count.value += 1
}
function dec() {
count.value -= 1
}
return {
count,
inc,
dec,
}
}

View File

@@ -1,10 +0,0 @@
import type { MaybeRef } from '@vueuse/core'
export function useQuery(key?: MaybeRef<string>) {
const query = ref<AnyObject>({})
onLoad((q) => {
query.value = q || {}
})
const value = computed(() => (key ? query.value[unref(key)] : null))
return { query, value }
}

View File

@@ -0,0 +1,38 @@
// 可以将此代码放置于项目src/hooks/useColPickerData.ts中
import { useCascaderAreaData } from '@vant/area-data'
export type CascaderOption = {
text: string
value: string
children?: CascaderOption[]
}
/**
* 使用'@vant/area-data'作为数据源构造ColPicker组件的数据
* @returns
*/
export function useColPickerData() {
// '@vant/area-data' 数据源
const colPickerData: CascaderOption[] = useCascaderAreaData()
// 根据code查找子节点不传code则返回所有节点
function findChildrenByCode(data: CascaderOption[], code?: string): CascaderOption[] | null {
if (!code) {
return data
}
for (const item of data) {
if (item.value === code) {
return item.children || null
}
if (item.children) {
const childrenResult = findChildrenByCode(item.children, code)
if (childrenResult) {
return childrenResult
}
}
}
return null
}
return { colPickerData, findChildrenByCode }
}

View File

@@ -2,8 +2,8 @@
import PrivacyModal from '@/components/PrivacyModel.vue'
const tabbar = ref('index')
const menu = reactive([{ title: '首页', icon: 'home', name: 'index' }, { title: '代理', icon: 'share', name: 'agent' }, { title: 'AI律师', icon: 'user-avatar', name: 'ai' }, { title: '我的', icon: 'user', name: 'me' }])
const menu = reactive([{ title: '首页', icon: 'home', name: 'index' }, { title: 'AI律师', icon: 'chat', name: 'ai' }, { title: '我的', icon: 'user', name: 'me' }])
function tabChange({ value }) {
uni.switchTab({
@@ -25,9 +25,14 @@ onMounted(() => {
})
function toComplaint() {
uni.navigateTo({
url: '/pages/complaint',
})
// 直接使用plus.runtime.openURL在系统浏览器中打开链接
// #ifdef APP-PLUS
plus.runtime.openURL('https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9');
// #endif
// #ifdef H5
window.location.href = 'https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9';
// #endif
}
</script>
@@ -40,13 +45,18 @@ export default {
</script>
<template>
<slot />
<view class=" min-h-screen from-blue-100 to-white bg-gradient-to-b min-h-screen flex flex-col flex-1 pb-16 box-border">
<slot />
</view>
<view>
<wd-tabbar v-model="tabbar" custom-class="qnc-tabbar" shape="round" safe-area-inset-bottom fixed @change="tabChange">
<wd-tabbar-item v-for="(item, index) in menu" :key="index" :name="item.name" :title="item.title" :icon="item.icon" />
<wd-tabbar v-model="tabbar" custom-class="qnc-tabbar" shape="round" safe-area-inset-bottom fixed
@change="tabChange">
<wd-tabbar-item v-for="(item, index) in menu" :key="index" :name="item.name" :title="item.title"
:icon="item.icon" />
</wd-tabbar>
</view>
<view class="fixed bottom-24 right-4 z-1000 flex items-center rounded-3xl from-red-500 to-red-400 bg-gradient-to-b px-2 py-1 text-center text-white shadow-2xl">
<view
class="fixed bottom-24 right-4 z-1000 flex items-center rounded-3xl from-red-500 to-red-400 bg-gradient-to-b px-2 py-1 text-center text-white shadow-2xl">
<wd-icon name="warning" class="mr-1" size="18px" />
<view class="text-xs" @click="toComplaint">
投诉
@@ -59,4 +69,6 @@ export default {
:deep(.qnc-tabbar) {
bottom: 16px !important;
}
</style>

View File

@@ -2,10 +2,15 @@ import { createSSRApp } from 'vue'
import App from './App.vue'
import 'uno.css'
import '@/app.scss'
import { setupRouterGuard } from '@/utils/routerGuard'
export function createApp() {
const app = createSSRApp(App)
// 初始化路由守卫
setupRouterGuard()
return {
app,
app
}
}

View File

@@ -16,7 +16,8 @@
"delay": 0
},
"modules": {
"Payment": {}
"Payment": {},
"Share": {}
},
"distribute": {
"android": {
@@ -111,5 +112,23 @@
"h5": {
"darkmode": false,
"themeLocation": "theme.json"
},
"uts": {
"plugins": {
"webview": {
"version": "1.0.0",
"description": "Web视图插件支持在App内打开网页",
"platforms": {
"android": {
"appid": "__UNI_WEBVIEW_ANDROID",
"autostart": false
},
"ios": {
"appid": "__UNI_WEBVIEW_IOS",
"autostart": false
}
}
}
}
}
}

View File

@@ -3,42 +3,56 @@
{
"path": "pages/index",
"type": "home",
"layout": "home",
"style": {
"navigationBarTextStyle": "white",
"transparentTitle": "always"
}
},
{
"path": "pages/agent",
"type": "page",
"layout": "home"
},
{
"path": "pages/agentVip",
"type": "page",
"layout": "page",
"title": "代理会员",
"agent": true,
"auth": true
},
{
"path": "pages/agentVipConfig",
"type": "page",
"layout": "page",
"title": "会员代理报告配置",
"agent": true,
"auth": true
},
{
"path": "pages/agreement",
"type": "page"
},
{
"path": "pages/ai",
"type": "page",
"layout": "home"
},
{
"path": "pages/authorization",
"path": "pages/invitation",
"type": "page",
"layout": "page",
"title": "授权书"
"title": "邀请下级",
"auth": true,
"agent": true
},
{
"path": "pages/complaint",
"path": "pages/invitationAgentApply",
"type": "page",
"layout": "page",
"title": "投诉服务"
},
{
"path": "pages/example copy",
"type": "page",
"layout": "page",
"title": "报告示例"
},
{
"path": "pages/example",
"type": "page",
"layout": "page",
"title": "示例报告"
},
{
"path": "pages/inquire",
"type": "page",
"layout": "page",
"title": "报告查询"
"title": "代理申请",
"auth": true
},
{
"path": "pages/login",
@@ -52,52 +66,55 @@
"layout": "home"
},
{
"path": "pages/pay",
"path": "pages/promote",
"type": "page",
"layout": "page",
"title": "全能查收款"
"title": "推广",
"agent": true,
"auth": true
},
{
"path": "pages/payb",
"path": "pages/promoteDetails",
"type": "page",
"layout": "page",
"title": "全能查收款"
},
{
"path": "pages/privacyPolicy",
"type": "page",
"layout": "page",
"title": "隐私政策"
"title": "直推报告",
"agent": true,
"auth": true
},
{
"path": "pages/queryHistory",
"type": "page",
"layout": "page",
"title": "历史报告"
"title": "历史报告",
"auth": true
},
{
"path": "pages/result copy",
"path": "pages/rewardsDetails",
"type": "page",
"layout": "page",
"title": "报告结果"
"title": "收益明细",
"agent": true,
"auth": true
},
{
"path": "pages/result",
"type": "page",
"layout": "page",
"title": "报告结果"
"path": "pages/vip",
"type": "page"
},
{
"path": "pages/service",
"path": "pages/withdraw",
"type": "page",
"layout": "page",
"title": "客户服务"
"title": "提现",
"auth": true,
"agent": true
},
{
"path": "pages/userAgreement",
"path": "pages/withdrawDetails",
"type": "page",
"layout": "page",
"title": "用户协议"
"title": "提现记录",
"auth": true,
"agent": true
}
],
"globalStyle": {
@@ -121,6 +138,11 @@
"text": "",
"visible": false
},
{
"pagePath": "pages/agent",
"text": "",
"visible": false
},
{
"pagePath": "pages/ai",
"text": "",

249
src/pages/agent.vue Normal file
View File

@@ -0,0 +1,249 @@
<script setup>
import { ref, computed } from 'vue'
import { getAgentRevenue } from '@/api/apis'
// 日期选项映射
const dateRangeMap = {
today: 'today',
week: 'last7d',
month: 'last30d'
}
// 直推报告数据
const promoteDateOptions = [
{ label: '今日', value: 'today' },
{ label: '近7天', value: 'week' },
{ label: '近1月', value: 'month' }
]
const selectedPromoteDate = ref('today')
// 活跃下级数据
const activeDateOptions = [
{ label: '今日', value: 'today' },
{ label: '近7天', value: 'week' },
{ label: '近1月', value: 'month' }
]
const selectedActiveDate = ref('today')
const data = ref(null)
// 计算当前直推数据
const currentPromoteData = computed(() => {
const range = dateRangeMap[selectedPromoteDate.value]
return data.value?.direct_push?.[range] || { commission: 0, report: 0 }
})
// 计算当前活跃数据
const currentActiveData = computed(() => {
const range = dateRangeMap[selectedActiveDate.value]
return data.value?.active_reward?.[range] || {
active_reward: 0,
sub_promote_reward: 0,
sub_upgrade_reward: 0,
sub_withdraw_reward: 0
}
})
const getData = async () => {
try {
const res = await getAgentRevenue()
if (res.code === 200) {
data.value = res.data
}
} catch (error) {
console.error(error)
}
}
onBeforeMount(() => {
if (uni.getStorageSync('token')) {
getData()
}
})
// 路由跳转
function goToPromoteDetail() {
uni.navigateTo({
url: '/pages/promoteDetails'
})
}
function goToActiveDetail() {
uni.navigateTo({
url: '/pages/rewardsDetails'
})
}
function toWithdraw() {
uni.navigateTo({
url: '/pages/withdraw'
})
}
function toWithdrawDetails() {
uni.navigateTo({
url: '/pages/withdrawDetails'
})
}
</script>
<template>
<view class="safe-area-top p-4 min-h-screen">
<!-- 资产卡片 -->
<view class="rounded-xl shadow-lg mb-4 bg-gradient-to-r from-blue-50/70 to-blue-100/50 p-6">
<view class="flex justify-between items-center mb-3">
<view class="flex items-center">
<wd-icon name="balance-pay" class="text-blue-500 text-xl mr-2" />
<text class="text-lg font-bold text-gray-800">余额</text>
</view>
<text class="text-3xl text-blue-600 font-bold">¥ {{ (data?.balance || 0).toFixed(2) }}</text>
</view>
<view class="text-sm text-gray-500 mb-2">累计收益¥ {{ (data?.total_earnings || 0).toFixed(2) }}</view>
<view class="text-sm text-gray-500 mb-6">冻结余额¥ {{ (data?.frozen_balance || 0).toFixed(2) }}</view>
<view class="grid grid-cols-2 gap-3">
<view @click="toWithdraw"
class="bg-gradient-to-r from-blue-500 to-blue-400 text-white rounded-full py-2 px-4 shadow-md flex items-center justify-center">
<wd-icon name="gold-coin" class="mr-1" />
<text>提现</text>
</view>
<view @click="toWithdrawDetails"
class="bg-white/90 text-gray-600 border border-gray-200/50 rounded-full py-2 px-4 shadow-sm flex items-center justify-center">
<wd-icon name="notes" class="mr-1" />
<text>提现记录</text>
</view>
</view>
</view>
<!-- 直推报告收益 -->
<view class="rounded-xl shadow-lg mb-4 bg-gradient-to-r from-blue-50/40 to-cyan-50/50 p-6">
<view class="flex justify-between items-center mb-4">
<view class="flex items-center">
<wd-icon name="balance-list" class="text-blue-400 text-xl mr-2" />
<text class="text-lg font-bold text-gray-800">直推报告收益</text>
</view>
<view class="text-right">
<text class="text-2xl text-blue-600 font-bold">¥ {{ (data?.direct_push?.total_commission || 0).toFixed(2)
}}</text>
<view class="text-sm text-gray-500 mt-1">有效报告 {{ data?.direct_push?.total_report || 0 }} </view>
</view>
</view>
<!-- 日期选择 -->
<view class="grid grid-cols-3 gap-2 mb-6">
<view v-for="item in promoteDateOptions" :key="item.value" @click="selectedPromoteDate = item.value" :class="[
'rounded-full transition-all py-1 px-4 text-sm',
selectedPromoteDate === item.value
? 'bg-blue-500 text-white shadow-md'
: 'bg-white/90 text-gray-600 border border-gray-200/50'
]">
{{ item.label }}
</view>
</view>
<view class="grid grid-cols-2 gap-4 mb-6">
<view class="bg-blue-50/60 p-3 rounded-lg backdrop-blur-sm">
<view class="flex items-center text-sm text-gray-500">
<wd-icon name="gold-coin" class="mr-1" />
<text>本日收益</text>
</view>
<text class="text-xl text-blue-600 font-bold mt-1">¥ {{ currentPromoteData.commission?.toFixed(2) || '0.00'
}}</text>
</view>
<view class="bg-blue-50/60 p-3 rounded-lg backdrop-blur-sm">
<view class="flex items-center text-sm text-gray-500">
<wd-icon name="description" class="mr-1" />
<text>有效报告</text>
</view>
<text class="text-xl text-blue-600 font-bold mt-1">{{ currentPromoteData.report || 0 }} </text>
</view>
</view>
<view class="flex items-center justify-between text-blue-500 text-sm font-semibold" @click="goToPromoteDetail">
<text>查看收益明细</text>
<text class="text-lg"></text>
</view>
</view>
<!-- 活跃下级奖励 -->
<view class="rounded-xl shadow-lg bg-gradient-to-r from-green-50/40 to-cyan-50/30 p-6">
<view class="flex justify-between items-center mb-4">
<view class="flex items-center">
<wd-icon name="friends" class="text-green-500 text-xl mr-2" />
<text class="text-lg font-bold text-gray-800">活跃下级奖励</text>
</view>
<view class="text-right">
<text class="text-2xl text-green-600 font-bold">¥ {{ (data?.active_reward?.total_reward || 0).toFixed(2)
}}</text>
<view class="text-sm text-gray-500 mt-1">活跃下级 0 </view>
</view>
</view>
<!-- 日期选择 -->
<view class="grid grid-cols-3 gap-2 mb-6">
<view v-for="item in activeDateOptions" :key="item.value" @click="selectedActiveDate = item.value" :class="[
'rounded-full transition-all py-1 px-4 text-sm',
selectedActiveDate === item.value
? 'bg-green-500 text-white shadow-md'
: 'bg-white/90 text-gray-600 border border-gray-200/50'
]">
{{ item.label }}
</view>
</view>
<view class="grid grid-cols-2 gap-2 mb-6">
<view class="bg-green-50/60 p-3 rounded-lg backdrop-blur-sm">
<view class="flex items-center text-sm text-gray-500">
<wd-icon name="medal" class="mr-1" />
<text>本日奖励</text>
</view>
<text class="text-xl text-green-600 font-bold mt-1">¥ {{ (currentActiveData.active_reward || 0).toFixed(2)
}}</text>
</view>
<view class="bg-green-50/60 p-3 rounded-lg backdrop-blur-sm">
<view class="flex items-center text-sm text-gray-500">
<wd-icon name="discount" class="mr-1" />
<text>下级推广奖励</text>
</view>
<text class="text-xl text-green-600 font-bold mt-1">¥ {{ (currentActiveData.sub_promote_reward ||
0).toFixed(2) }}</text>
</view>
<view class="bg-green-50/60 p-3 rounded-lg backdrop-blur-sm">
<view class="flex items-center text-sm text-gray-500">
<wd-icon name="contact" class="mr-1" />
<text>新增活跃奖励</text>
</view>
<text class="text-xl text-green-600 font-bold mt-1">¥ {{ (currentActiveData.sub_upgrade_reward ||
0).toFixed(2) }}</text>
</view>
<view class="bg-green-50/60 p-3 rounded-lg backdrop-blur-sm">
<view class="flex items-center text-sm text-gray-500">
<wd-icon name="fire" class="mr-1" />
<text>下级转化奖励</text>
</view>
<text class="text-xl text-green-600 font-bold mt-1">¥ {{ (currentActiveData.sub_withdraw_reward ||
0).toFixed(2) }}</text>
</view>
</view>
<view class="flex items-center justify-between text-green-500 text-sm font-semibold" @click="goToActiveDetail">
<text>查看奖励明细</text>
<text class="text-lg"></text>
</view>
</view>
</view>
</template>
<style>
button {
transition: all 0.2s ease;
}
button:hover {
transform: translateY(-1px);
}
</style>
<route lang="json">{
"layout": "home"
}</route>

63
src/pages/agentVip.vue Normal file
View File

@@ -0,0 +1,63 @@
<template>
<view class="relative">
<image class="w-full" src="/static/image/vip_bg.png" mode="widthFix" />
<view @click="toService" class="service-btn">
点击马上报名
</view>
</view>
</template>
<script setup>
function toService() {
// 直接使用plus.runtime.openURL在系统浏览器中打开链接
// #ifdef APP-PLUS
plus.runtime.openURL('https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9');
// #endif
// #ifdef H5
window.location.href = 'https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9';
// #endif
// #ifdef MP
uni.navigateTo({
url: '/pages/agreement?url=' + encodeURIComponent('https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9')
});
// #endif
}
</script>
<style lang="scss" scoped>
.relative {
position: relative;
width: 100%;
height: 100%;
}
.service-btn {
position: absolute;
left: 50%;
bottom: 600rpx;
transform: translateX(-50%);
background: linear-gradient(to right, #2d3748, #000000, #2d3748);
padding: 10rpx 20rpx;
border-radius: 16rpx;
color: #ffffff;
font-size: 48rpx;
font-weight: bold;
box-shadow: 0 0 30rpx rgba(255, 255, 255, 0.3);
transition: transform 0.3s;
&:active {
transform: translateX(-50%) scale(1.05);
}
}
</style>
<route lang="json">
{
"layout": "page",
"title": "代理会员",
"agent": true,
"auth": true
}
</route>

View File

@@ -0,0 +1,504 @@
<template>
<view class="p-4 mx-auto min-h-screen">
<!-- 标题部分 -->
<view class="card mb-4 p-4 bg-gradient-to-r from-blue-500 to-blue-600 rounded-lg shadow-lg text-white">
<text class="text-2xl font-extrabold mb-2 block">专业报告定价配置</text>
<text class="opacity-90 block">请选择报告类型并设置定价策略助您实现精准定价</text>
</view>
<view class="mb-4 bg-white rounded-lg overflow-hidden px-4 flex items-center justify-between">
<span class="text-blue-600 font-medium text-sm">📝 选择报告</span>
<wd-picker custom-class="flex-1" v-model="selectedReportText" :columns="reportOptions" title="选择报告类型"
@confirm="onConfirm" />
</view>
<view v-if="selectedReportText" class="space-y-6">
<!-- 配置卡片 -->
<view class="card">
<!-- 当前报告标题 -->
<view class="flex items-center mb-6">
<text class="text-xl font-semibold text-gray-800">
{{ selectedReportText }}配置
</text>
</view>
<!-- 显示当前产品的基础成本信息 -->
<view v-if="productConfigData && productConfigData.cost_price"
class="px-4 py-2 mb-4 bg-gray-50 border border-gray-200 rounded-lg shadow-sm">
<text class="text-lg font-semibold text-gray-700 block">报告基础配置信息</text>
<view class="mt-1 text-sm text-gray-600">
<text class="block">基础成本价<text class="font-medium">{{ productConfigData.cost_price }}</text> </text>
<text class="block">最高设定金额上限<text class="font-medium">{{ productConfigData.price_range_max }}</text>
</text>
<text class="block">最高设定比例上限<text class="font-medium">{{ priceRatioMax }}</text> %</text>
</view>
</view>
<!-- 分隔线 -->
<view class="my-6 flex items-center justify-center">
<view class="bg-gray-200 h-px flex-1"></view>
<text class="mx-2 text-gray-400 text-sm">成本策略配置</text>
<view class="bg-gray-200 h-px flex-1"></view>
</view>
<!-- 表单部分 -->
<wd-form>
<!-- 加价金额 -->
<wd-form-item label="加价金额" prop="price_increase_amount">
<wd-input v-model="configData.price_increase_amount" type="number" placeholder="0"
@blur="validateDecimal('price_increase_amount')" />
</wd-form-item>
<view class="text-xs text-gray-400 mt-1">
<text class="block">提示最大加价金额为{{ priceIncreaseAmountMax }}</text>
<text class="block">说明加价金额是在基础成本价上增加的额外费用决定下级报告的最低定价您将获得所有输入的金额利润</text>
</view>
<!-- 分隔线 -->
<view class="my-6 flex items-center justify-center">
<view class="bg-gray-200 h-px flex-1"></view>
<text class="mx-2 text-gray-400 text-sm">定价策略配置</text>
<view class="bg-gray-200 h-px flex-1"></view>
</view>
<!-- 定价区间最低 -->
<wd-form-item label="定价区间最低" prop="price_range_from">
<wd-input v-model="configData.price_range_from" type="number" placeholder="0"
@blur="() => { validateDecimal('price_range_from'); validateRange(); }" />
</wd-form-item>
<view class="text-xs text-gray-400 mt-1">
<text class="block">提示定价区间最低金额不能低于基础最低 {{ productConfigData?.price_range_min || 0 }} + 加价金额</text>
<text class="block">说明设定的定价区间最低金额为定价区间的起始值若下级设定的报告金额在区间内则区间内部分将按比例获得收益</text>
</view>
<!-- 定价区间最高 -->
<wd-form-item label="定价区间最高" prop="price_range_to">
<wd-input v-model="configData.price_range_to" type="number" placeholder="0"
@blur="() => { validateDecimal('price_range_to'); validateRange(); }" />
</wd-form-item>
<view class="text-xs text-gray-400 mt-1">
<text class="block">提示定价区间最高金额不能超过上限{{ productConfigData?.price_range_max || 0 }}和大于定价区间最低金额{{
priceIncreaseMax
}}</text>
<text class="block">说明设定的定价区间最高金额为定价区间的结束值若下级设定的报告金额在区间内则区间内部分将按比例获得收益</text>
</view>
<!-- 收取比例 -->
<wd-form-item label="收取比例" prop="price_ratio">
<wd-input v-model="configData.price_ratio" type="number" placeholder="0" @blur="validateRatio" />
</wd-form-item>
<view class="text-xs text-gray-400 mt-1">
<text class="block">提示最大收取比例为{{ priceRatioMax }}%</text>
<text class="block">说明收取比例表示对定价区间内即报告金额超过最低金额小于最高金额的部分的金额按此比例进行利润分成</text>
</view>
</wd-form>
</view>
<!-- 保存按钮 -->
<button type="primary" class="bg-blue-500 text-white py-1 rounded-xl w-full" @click="handleSubmit">
保存当前报告配置
</button>
</view>
<!-- 未选择提示 -->
<view v-else class="text-center py-12">
<text class="text-gray-400 text-4xl block mb-4"></text>
<text class="text-gray-500 block">请先选择需要配置的报告类型</text>
</view>
</view>
</template>
<script setup>
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { getAgentMembershipUserConfig, saveAgentMembershipUserConfig } from '@/apis/agent'
// 报告类型选项
const reportOptions = [
{ label: '人事背调', value: 1 },
{ label: '老板企业报告', value: 2 },
{ label: '家政风险', value: 3 },
{ label: '婚恋风险', value: 4 },
{ label: '贷前背调', value: 5 },
{ label: '租赁风险', value: 6 },
{ label: '个人风险', value: 7 },
]
// 状态管理
const showPicker = ref(false)
const selectedReportId = ref(1)
const selectedReportText = ref('人事背调')
const configData = ref({})
const productConfigData = ref({})
const priceIncreaseMax = ref(null)
const priceIncreaseAmountMax = ref(null)
const priceRatioMax = ref(null)
const rangeError = ref(false)
const ratioError = ref(false)
const increaseError = ref(false)
// 金额输入格式验证:确保最多两位小数
const validateDecimal = (field) => {
console.log(`validateDecimal开始: field=${field}, 值=${configData.value[field]}`)
const value = configData.value[field]
if (value === null || value === undefined) {
console.log(`validateDecimal: ${field}为空,退出验证`)
return
}
const numValue = Number(value)
if (isNaN(numValue)) {
console.log(`validateDecimal: ${field}无法转换为数字设置为null`)
configData.value[field] = null
return
}
const fixedValue = parseFloat(numValue.toFixed(2))
console.log(`validateDecimal: ${field}原值=${numValue},处理后=${fixedValue}`)
configData.value[field] = fixedValue
if (field === 'price_increase_amount') {
console.log(`validateDecimal: 检查加价金额上限 ${fixedValue} vs ${priceIncreaseAmountMax.value}`)
if (fixedValue > priceIncreaseAmountMax.value) {
configData.value[field] = priceIncreaseAmountMax.value
console.log(`validateDecimal: 加价金额超过上限,已修正为${priceIncreaseAmountMax.value}`)
uni.showToast({
title: `加价金额最大为${priceIncreaseAmountMax.value}`,
icon: 'none'
})
increaseError.value = true
setTimeout(() => {
increaseError.value = false
}, 2000)
} else {
increaseError.value = false
}
// 当加价金额改变后,重新验证价格区间
validateRange()
}
console.log(`validateDecimal结束: ${field}最终值=${configData.value[field]}`)
}
// 价格区间验证
const validateRange = () => {
console.log('validateRange开始:',
`最低=${configData.value.price_range_from}`,
`最高=${configData.value.price_range_to}`)
// if (configData.value.price_range_from === null || configData.value.price_range_to === null) {
// console.log('validateRange: 价格区间值为null退出验证')
// rangeError.value = false
// return
// }
if (isNaN(configData.value.price_range_from) || isNaN(configData.value.price_range_to)) {
console.log('validateRange: 价格区间值非数字,退出验证')
return
}
const additional = configData.value.price_increase_amount || 0
console.log(`validateRange: 加价金额=${additional}`)
const minAllowed = parseFloat(
(Number(productConfigData.value.cost_price) + Number(additional)).toFixed(2)
) // 使用成本价作为最小值
const maxAllowed = productConfigData.value.price_range_max // 使用产品配置中的最大价格作为最大值
console.log(`validateRange: 最低允许=${minAllowed}, 最高允许=${maxAllowed}`)
// 检查最低金额
if (configData.value.price_range_from < minAllowed) {
console.log(`validateRange: 定价区间最低金额(${configData.value.price_range_from})小于允许最低值(${minAllowed}),进行修正`)
configData.value.price_range_from = minAllowed
uni.showToast({
title: `定价区间最低金额不能低于成本价 ${minAllowed}`,
icon: 'none'
})
rangeError.value = true
closeRangeError()
configData.value.price_range_to = parseFloat(
(Number(configData.value.price_range_from) + Number(priceIncreaseMax.value)).toFixed(2)
)
console.log(`validateRange: 已调整最高金额为 ${configData.value.price_range_to}`)
return
}
// 检查最高金额是否小于最低金额
if (configData.value.price_range_to < configData.value.price_range_from) {
console.log(`validateRange: 定价区间最高金额(${configData.value.price_range_to})小于最低金额(${configData.value.price_range_from}),进行修正`)
uni.showToast({
title: '定价区间最高金额不能低于定价区间最低金额',
icon: 'none'
})
if (configData.value.price_range_from + priceIncreaseMax.value > maxAllowed) {
configData.value.price_range_to = maxAllowed
console.log(`validateRange: 最高值已修正为最大允许值 ${maxAllowed}`)
} else {
configData.value.price_range_to = configData.value.price_range_from + priceIncreaseMax.value
console.log(`validateRange: 最高值已修正为最低金额+最大增加值 ${configData.value.price_range_to}`)
}
rangeError.value = true
closeRangeError()
return
}
// 检查差值
const diff = parseFloat(
(configData.value.price_range_to - configData.value.price_range_from).toFixed(2)
)
console.log(`validateRange: 价格区间差值=${diff}, 最大允许差值=${priceIncreaseMax.value}`)
if (diff > priceIncreaseMax.value) {
console.log(`validateRange: 价格区间差值超过最大允许值,进行修正`)
uni.showToast({
title: `价格区间最大差值为${priceIncreaseMax.value}`,
icon: 'none'
})
configData.value.price_range_to = parseFloat(
(Number(configData.value.price_range_from) + Number(priceIncreaseMax.value)).toFixed(2)
)
console.log(`validateRange: 已调整最高金额为 ${configData.value.price_range_to}`)
closeRangeError()
return
}
// 检查最高金额是否超过上限
if (configData.value.price_range_to > maxAllowed) {
console.log(`validateRange: 定价区间最高金额(${configData.value.price_range_to})超过上限(${maxAllowed}),进行修正`)
configData.value.price_range_to = maxAllowed
uni.showToast({
title: `定价区间最高金额不能超过 ${maxAllowed}`,
icon: 'none'
})
closeRangeError()
}
if (!rangeError.value) {
rangeError.value = false
}
console.log('validateRange结束:',
`最终最低=${configData.value.price_range_from}`,
`最终最高=${configData.value.price_range_to}`)
}
// 收取比例验证(修改为保留两位小数,不再四舍五入取整)
const validateRatio = () => {
console.log(`validateRatio开始: 值=${configData.value.price_ratio}`)
let value = configData.value.price_ratio
if (value === null || value === undefined) {
console.log('validateRatio: 值为空,退出验证')
return
}
const numValue = Number(value)
if (isNaN(numValue)) {
console.log('validateRatio: 值无法转换为数字设置为null')
configData.value.price_ratio = null
ratioError.value = true
return
}
console.log(`validateRatio: 检查比例范围 ${numValue} vs 最大值${priceRatioMax.value}`)
if (numValue > priceRatioMax.value) {
console.log(`validateRatio: 比例超过最大值,已修正为${priceRatioMax.value}`)
configData.value.price_ratio = priceRatioMax.value
uni.showToast({
title: `收取比例最大为${priceRatioMax.value}%`,
icon: 'none'
})
ratioError.value = true
setTimeout(() => {
ratioError.value = false
}, 1000)
} else if (numValue < 0) {
console.log('validateRatio: 比例小于0已修正为0')
configData.value.price_ratio = 0
ratioError.value = true
} else {
configData.value.price_ratio = parseFloat(numValue.toFixed(2))
ratioError.value = false
}
console.log(`validateRatio结束: 最终值=${configData.value.price_ratio}`)
}
// 获取配置
const getConfig = async () => {
try {
console.log(`getConfig开始: 获取产品ID=${selectedReportId.value}的配置`)
const res = await getAgentMembershipUserConfig({ product_id: selectedReportId.value })
if (res.code === 200) {
const respConfigData = res.data.agent_membership_user_config
console.log("respConfigData", respConfigData)
configData.value = {
id: respConfigData.product_id,
price_range_from: respConfigData.price_range_from || null,
price_range_to: respConfigData.price_range_to || null,
price_ratio: respConfigData.price_ratio * 100 || null, // 转换为百分比
price_increase_amount: respConfigData.price_increase_amount || null,
}
productConfigData.value = res.data.product_config
// 设置动态限制值
priceIncreaseMax.value = res.data.price_increase_max
priceIncreaseAmountMax.value = res.data.price_increase_amount
priceRatioMax.value = res.data.price_ratio * 100
console.log('getConfig: 配置加载成功',
`最大差值=${priceIncreaseMax.value}`,
`最大加价=${priceIncreaseAmountMax.value}`,
`最大比例=${priceRatioMax.value}%`)
console.log('getConfig: 当前配置', configData.value)
}
} catch (error) {
console.error("getConfig错误:", error)
uni.showToast({
title: '配置加载失败',
icon: 'none'
})
}
}
// 提交处理
const handleSubmit = async () => {
try {
if (!finalValidation()) {
return
}
// 前端数据转换
const submitData = {
product_id: configData.value.id,
price_range_from: configData.value.price_range_from || 0,
price_range_to: configData.value.price_range_to || 0,
price_ratio: (configData.value.price_ratio || 0) / 100, // 转换为小数
price_increase_amount: configData.value.price_increase_amount || 0,
}
const res = await saveAgentMembershipUserConfig(submitData)
if (res.code === 200) {
uni.showToast({
title: '保存成功',
icon: 'success'
})
getConfig()
}
} catch (error) {
uni.showToast({
title: '保存失败,请稍后重试',
icon: 'none'
})
}
}
// 最终验证函数
const finalValidation = () => {
// 校验最低金额不能为空且大于0
if (!configData.value.price_range_from || configData.value.price_range_from <= 0) {
uni.showToast({
title: "定价区间最低金额不能为空",
icon: 'none'
})
return false
}
// 校验最高金额不能为空且大于0
if (!configData.value.price_range_to || configData.value.price_range_to <= 0) {
uni.showToast({
title: "定价区间最高金额不能为空",
icon: 'none'
})
return false
}
// 校验收取比例不能为空且大于0
if (!configData.value.price_ratio || configData.value.price_ratio <= 0) {
uni.showToast({
title: "收取比例不能为空",
icon: 'none'
})
return false
}
// 验证最低金额必须小于最高金额
if (configData.value.price_range_from >= configData.value.price_range_to) {
uni.showToast({
title: "定价区间最低金额必须小于定价区间最高金额",
icon: 'none'
})
return false
}
// 验证价格区间差值不能超过最大允许差值
const finalDiff = parseFloat(
(configData.value.price_range_to - configData.value.price_range_from).toFixed(2)
)
if (finalDiff > priceIncreaseMax.value) {
uni.showToast({
title: `价格区间最大差值为${priceIncreaseMax.value}`,
icon: 'none'
})
return false
}
// 验证最高金额不能超过产品配置中设定的上限
if (configData.value.price_range_to > productConfigData.value.price_range_max) {
uni.showToast({
title: `定价区间最高金额不能超过${productConfigData.value.price_range_max}`,
icon: 'none'
})
return false
}
// 验证最低金额不能低于成本价+加价金额(加价金额允许为空)
const additional = configData.value.price_increase_amount || 0
if (configData.value.price_range_from < productConfigData.value.cost_price + additional) {
uni.showToast({
title: `定价区间最低金额不能低于成本价${productConfigData.value.cost_price + additional}`,
icon: 'none'
})
return false
}
return true
}
// 选择器确认
const onConfirm = (e) => {
const { selectedItems } = e
selectedReportId.value = selectedItems.value
selectedReportText.value = selectedItems.label
showPicker.value = false
// 重置错误状态
rangeError.value = false
ratioError.value = false
increaseError.value = false
getConfig()
}
const closeRangeError = () => {
setTimeout(() => {
rangeError.value = false
}, 2000)
}
onMounted(() => {
getConfig()
})
</script>
<style scoped>
.card {
border-radius: 12px;
background-color: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
padding: 16px;
margin-bottom: 16px;
}
.space-y-6>* {
margin-bottom: 24px;
}
</style>
<route type="page" lang="json">{
"layout": "page",
"title": "会员代理报告配置",
"agent": true,
"auth": true
}</route>

63
src/pages/agreement.vue Normal file
View File

@@ -0,0 +1,63 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
// 从环境变量获取基础URL
const BASE_URL = import.meta.env.VITE_APP_BASE_URL || 'https://www.quannengcha.com'
// 协议路径和标题的映射
const agreementMap = {
user: {
path: '/app/userAgreement',
title: '用户协议'
},
privacy: {
path: '/app/privacyPolicy',
title: '隐私政策'
},
authorization: {
path: '/app/authorization',
title: '授权书'
},
service: {
path: '/app/agentSerivceAgreement',
title: '信息技术服务合同'
},
manage: {
path: '/app/agentManageAgreement',
title: '推广方管理制度协议'
}
}
const agreementUrl = ref('')
const pageTitle = ref('协议')
// 使用 uniapp 的 onLoad 生命周期钩子获取页面参数
onLoad((option) => {
const type = option.type || 'user'
if (agreementMap[type]) {
agreementUrl.value = `${BASE_URL}${agreementMap[type].path}`
pageTitle.value = agreementMap[type].title
// 设置标题 - 此标题会传递给 page 布局中的 wd-navbar
uni.setNavigationBarTitle({
title: pageTitle.value
})
}
})
function handleClickLeft() {
uni.navigateBack()
}
</script>
<template>
<view>
<wd-navbar :title="pageTitle" left-text="返回" placeholder left-arrow safe-area-inset-top fixed @click-left="handleClickLeft" />
<web-view :webview-styles="webviewStyles" :src="agreementUrl" />
</view>
</template>

View File

@@ -1,72 +1,254 @@
<script setup>
import { onMounted, ref } from 'vue'
const userMessage = ref('')
const messages = ref([
{ sender: 'ai', text: '欢迎!请问有什么可以帮助您的吗?' },
])
function sendMessage() {
if (userMessage.value.trim() === '')
return
messages.value.push({ sender: 'user', text: userMessage.value })
// AI 统一回复(中文套话)
setTimeout(() => {
messages.value.push({
sender: 'ai',
text: '感谢您的提问!我们会尽力为您提供帮助。',
})
}, 1000)
userMessage.value = ''
}
const safeAreaTop = ref(44)
onShow(() => {
uni.getSystemInfo({
success: (res) => {
if (res.safeArea && res.safeArea.top) {
safeAreaTop.value = res.safeArea.top // 设置安全区顶部距离
}
},
})
})
</script>
<template>
<view
class="box-border min-h-screen from-blue-100 to-white bg-gradient-to-b" style="paddingTop:44px"
>
<view class="chat-page mx-4 flex flex-col rounded-xl shadow-lg">
<view class="chat-window flex-1 overflow-auto border p-4">
<view v-for="(message, index) in messages" :key="index" class="mb-2">
<view v-if="message.sender === 'ai'" class="inline-block max-w-max rounded-xl bg-white p-2 text-left text-green-600 font-medium shadow-md">
{{ message.text }}
</view>
<view v-else class="ml-auto inline-block max-w-max rounded-xl from-sky-300 via-sky-300 to-sky-300 bg-gradient-to-r p-2 text-right text-white font-medium shadow-md">
{{ message.text }}
<view class="safe-area-top flex flex-col box-border from-blue-100 to-white bg-gradient-to-b pt-4 flex-1 pb-4">
<!-- 角色切换部分 -->
<view class="flex border-blue-300 mx-4 p-1 bg-white rounded-xl">
<view class="flex items-center flex-1 p-2 box-border rounded-xl cursor-pointer"
:class="selectedRole === 'legal' ? 'bg-blue-300 text-white' : ''" @click="selectRole('legal')">
<image src="/static/image/ai_picture.webp" class="w-10 h-10 rounded-xl mr-2" alt="AI律师" />
法律咨询
</view>
<view class="flex items-center flex-1 p-2 box-border rounded-xl cursor-pointer"
:class="selectedRole === 'emotional' ? 'bg-blue-300 text-white' : ''" @click="selectRole('emotional')">
<image src="/static/image/ai_qinggan.png" class="w-10 h-10 rounded-xl mr-2" alt="AI心理咨询师" />
情感咨询
</view>
</view>
<!-- 聊天窗口 -->
<view class="mx-4 flex flex-col flex-1 rounded-xl shadow-lg">
<view class="flex flex-col flex-1 p-4">
<view class="flex-1 overflow-y-auto">
<view v-for="(message, index) in currentMessages" :key="index" class="mb-4">
<view v-if="message.sender === 'ai'" class="flex justify-start items-start">
<!-- 根据角色显示不同的AI形象 -->
<image :src="selectedRole === 'legal' ? '/static/image/ai_picture.webp' : '/static/image/ai_qinggan.png'"
class=" flex-shrink-0 w-10 h-10 rounded-xl mr-2" :alt="selectedRole === 'legal' ? 'AI律师' : 'AI心理咨询师'" />
<view class="inline-block max-w-max rounded-xl bg-white p-2 text-left"
:class="selectedRole === 'legal' ? 'text-green-600' : 'text-purple-600'">
<!-- 如果是AI消息显示加载中或文本 -->
<view v-if="message.loading" class="flex justify-center items-center">
<view class="loader"></view> <!-- 加载动画 -->
</view>
<view v-else>
{{ message.text }}
</view>
</view>
</view>
<view v-else class="flex justify-end">
<view class="ml-auto inline-block max-w-max rounded-xl from-sky-300 via-sky-300 to-sky-300
bg-gradient-to-r p-2 text-right text-white font-medium shadow-md">
{{ message.text }}
</view>
</view>
</view>
</view>
</view>
<view class="input-area mx-2 flex items-center gap-2 p-4">
<wd-input v-model="userMessage" placeholder="请输入您的问题..." class="flex-1" size="large" />
<wd-button custom-class="shadow" type="primary" @click="sendMessage">
发送
</wd-button>
<!-- 输入区域 -->
<view class="p-2 w-full input-area flex items-center gap-2">
<input v-model="userMessage" :placeholder="selectedRole === 'legal' ? '请输入您的法律问题...' : '请输入您的情感问题...'"
class="flex-1 p-2 border rounded-lg" type="text" @confirm="sendMessage" />
<button class="shadow p-2 bg-blue-500 text-white rounded-lg" @click="sendMessage">
发送
</button>
</view>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.chat-page {
height: calc(100vh - 108px);
<script setup>
import { ref, onBeforeUnmount, computed } from 'vue'
import chatEncrypt from "@/utils/chatEncrypt"
// 当前选中的角色,默认是法律咨询
const selectedRole = ref('legal')
// 用户输入的消息
const userMessage = ref('')
// 存储每个角色的消息记录
const messages = ref({
legal: [
{ sender: 'ai', text: '欢迎!请问有什么法律问题需要帮助?' },
],
emotional: [
{ sender: 'ai', text: '欢迎!请问有什么情感问题需要帮助?' },
]
})
// 存储每个角色的 sessionID
const sessionID = ref({
legal: "",
emotional: ""
})
let reader = {
legal: null,
emotional: null
}
// 计算当前选中的角色的消息
const currentMessages = computed(() => messages.value[selectedRole.value])
// 选择角色
function selectRole(role) {
if (selectedRole.value !== role) {
selectedRole.value = role
// 如果该角色还没有消息记录,初始化欢迎消息
if (!messages.value[role]) {
messages.value[role] = [
{ sender: 'ai', text: role === 'legal' ? '欢迎!请问有什么法律问题需要帮助?' : '欢迎!请问有什么情感问题需要帮助?' },
]
sessionID.value[role] = ""
}
}
}
async function sendMessage() {
if (userMessage.value.trim() === '') return;
// 获取当前角色
const role = selectedRole.value
// 用户消息推入对应角色的消息列表
messages.value[role].push({ sender: 'user', text: userMessage.value })
const t = Date.now()
const x = chatEncrypt(String(t))
// 在消息列表中添加一个 AI 消息并标记为加载状态
const aiMessage = { sender: 'ai', text: '', loading: true }
messages.value[role].push(aiMessage)
console.log("import.meta.env.VITE_APP_BASE_URL", import.meta.env.VITE_APP_BASE_URL)
// 发起请求
try {
const response = await uni.request({
url: import.meta.env.VITE_APP_BASE_URL + '/api/v1/chat/send',
method: 'POST',
header: {
'Content-Type': 'application/json',
'x': x,
't': t,
},
data: {
prompt: userMessage.value,
platform_id: 2,
// roleid: role === 'legal' ? 1 : 2, // 根据角色选择不同的 roleid
role_id: 1, // 根据角色选择不同的 roleid
openid: 'openid' + uni.getStorageSync("token"),
userid: 'userid' + uni.getStorageSync("token"),
sessionid: sessionID.value[role] // 使用对应角色的 sessionID
},
responseType: 'text',
enableChunked: true, // 启用分块传输
enableStream: true, // 启用流式传输
success: (streamRes) => {
if (streamRes.statusCode === 200) {
aiMessage.loading = false;
// 处理流式响应
const chunks = streamRes.data.split('\n');
for (const chunk of chunks) {
if (chunk.trim()) {
let message = chunk;
if (message.startsWith('data:')) {
message = message.replace('data:', '').trim();
}
console.log("message", message);
try {
const parsedMessage = JSON.parse(message);
console.log("parsedMessage", parsedMessage);
if (parsedMessage?.output?.session_id) {
// 存储 session_id
sessionID.value[role] = parsedMessage?.output?.session_id;
}
// 获取 AI 回复的文本
const aiText = parsedMessage.output.text || '';
// 模拟打字机效果(逐字添加文本)
const addTextWithTypingEffect = (text) => {
if (!text) return;
// 直接添加到消息中(实时更新)
aiMessage.text += text;
// 强制更新视图
messages.value[role] = [...messages.value[role]];
};
// 执行打字机效果
addTextWithTypingEffect(aiText);
} catch (e) {
console.error('Failed to parse message:', e);
}
}
}
}
},
fail: (err) => {
console.error('Request failed:', err);
aiMessage.loading = false;
aiMessage.text = '抱歉,请求失败,请重试';
messages.value[role] = [...messages.value[role]];
}
});
} catch (error) {
console.error('Request error:', error);
}
userMessage.value = ''; // 清空输入框
}
onBeforeUnmount(() => {
// 在UniApp中不需要特别取消流读取UniApp会自动处理
})
</script>
<style scoped>
input {
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 0.5rem;
}
button {
padding: 0.5rem 1rem;
background-color: #007bff;
border: none;
border-radius: 0.5rem;
color: white;
}
button:hover {
background-color: #0056b3;
}
.loader {
border: 4px solid #f3f3f3;
/* Light gray */
border-top: 4px solid #3498db;
/* Blue */
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Tab Styles */
.flex.border-blue-300>view {
transition: all 0.3s;
}
</style>
<route lang="json">
{
"layout": "home"
}
</route>
<route lang="json">{
"layout": "home"
}</route>

View File

@@ -1,54 +0,0 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
const id = ref(null)
function handleMessage(event) {
const data = event.detail.data[0]
if (data.loaded) {
onWebViewLoaded()
}
else if (data.action === 'agreed') {
uni.redirectTo({ url: `/pages/pay?id=${id.value}` })
}
else if (data.action === 'cancelled') {
uni.showModal({
title: '注意',
content: '是否确认取消,退出当前页面',
success(res) {
if (res.confirm) {
uni.navigateBack()
}
},
})
}
}
function onWebViewLoaded() {
}
const src = ref('https://app.quannengcha.com/authorization')
onLoad((option) => {
if (option.id) {
src.value = `${src.value}?id=${encodeURIComponent(option.id)}&token=${encodeURIComponent(uni.getStorageSync('token'))}`
id.value = option.id
}
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" :src="src" @message="handleMessage" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "授权书"
}
</route>

View File

@@ -1,22 +0,0 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" src="https://app.quannengcha.com/complaint" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "投诉服务"
}
</route>

View File

@@ -1,204 +0,0 @@
<script setup>
import CBad from '@/ui/CBad.vue'
import CBankLoanApplication from '@/ui/CBankLoanApplication.vue'
import CBankLoanBehavior from '@/ui/CBankLoanBehavior.vue'
import CLawsuit from '@/ui/CLawsuit.vue'
import CRelatedEnterprises from '@/ui/CRelatedEnterprises.vue'
import CSpecialList from '@/ui/CSpecialList.vue'
import CTabs from '@/ui/CTabs.vue'
import { queryExample } from '@/api/apis'
import CMarriage from '@/ui/CMarriage.vue'
const productMap = {
1: '背景调查',
2: '企业报告',
3: '家政服务',
4: '婚姻状态',
5: '贷前背景调查',
6: '租赁服务',
7: '个人风险评估',
}
// 根据 product_id 获取产品名称
function getProductName(productId) {
return productMap[productId] || '未知类型'
}
const productId = ref(null)
const isDone = ref(false)
const entData = ref(null)
const lawsuitData = ref(null)
const badData = ref(null)
const specialData = ref(null)
const bankLoanApplicationData = ref(null)
const marriageData = ref(null)
const bankLoanBehavior = ref(null)
const tabs = ref([
{ label: '报告概述', value: 'overview' },
])
const reportItems = ref([
])
const sortedReportItems = computed(() => {
return reportItems.value.slice().sort((a, b) => a.sort - b.sort)
})
const sortedTabs = computed(() => {
return tabs.value.slice().sort((a, b) => a.sort - b.sort)
})
onLoad((option) => {
console.log('option', option)
const { feature } = option
if (feature) {
queryExample({ feature }).then((res) => {
console.log('res', res)
if (res.code === 200) {
productId.value = res.data.product_id
res.data.query_data.forEach((item) => {
if (item.success) {
switch (item.apiID) {
case 'G09SC02':
marriageData.value = item.data
tabs.value.push({ label: '婚姻状态', value: 'marriage', sort: 1 })
reportItems.value.push({ label: '婚姻状态', value: 'marriage', sort: 1 })
break
case 'G27BJ05':
bankLoanApplicationData.value = item.data
tabs.value.push({ label: '借贷申请记录', value: 'netloan', sort: 7 })
reportItems.value.push({ label: '借贷申请记录', value: 'netloan', sort: 7 })
break
case 'G28BJ05':
bankLoanBehavior.value = item.data
tabs.value.push({ label: '借贷记录', value: 'loan', sort: 6 })
reportItems.value.push({ label: '借贷记录', value: 'loan', sort: 6 })
break
case 'G26BJ05':
specialData.value = item.data
tabs.value.push({ label: '异常名单', value: 'special', sort: 5 })
reportItems.value.push({ label: '异常名单', value: 'special', sort: 5 })
break
case 'G05HZ01':
entData.value = item.data
tabs.value.push({ label: '关联企业', value: 'ent', sort: 4 })
reportItems.value.push({ label: '关联企业', value: 'ent', sort: 4 })
break
case 'G34BJ03':
badData.value = item.data
tabs.value.push({ label: '不良风险评估', value: 'bad', sort: 3 })
reportItems.value.push({ label: '不良风险评估', value: 'bad', sort: 3 })
break
case 'G35SC01':
lawsuitData.value = item.data
tabs.value.push({ label: '涉诉案件', value: 'lawsuit', sort: 2 })
reportItems.value.push({ label: '涉诉案件', value: 'lawsuit', sort: 2 })
break
default:
console.log(`未知的apiID: ${item.apiID}`)
}
}
})
}
}).finally(() => {
isDone.value = true
})
}
})
</script>
<template>
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
<CTabs
:tabs="sortedTabs"
type="blue-green"
/>
<template v-if="isDone">
<div class="flex flex-col gap-y-4 p-4 pt-12">
<div id="overview" class="title">
报告概述
</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<div class="flex justify-between">
<span class="text-gray-700 font-bold">报告时间</span>
<span class="text-gray-600">2024年11月18日 23:11:23</span>
</div>
<div class="flex justify-between">
<span class="text-gray-700 font-bold">报告项目</span>
<span class="text-gray-600">{{ getProductName(productId) }}</span>
</div>
</div>
<div>
<LTitle class="my-4" title="报告内容" type="blue-green" />
<div class="flex flex-col gap-y-2">
<div v-for="item in sortedReportItems" :key="item.value" class="flex justify-between">
<span class="text-gray-700 font-bold">{{ item.label }}</span>
<span class="text-green-500 font-bold">已解锁</span>
</div>
</div>
</div>
</div>
<template v-if="marriageData">
<div id="marriage" class="title">
婚姻状态
</div>
<CMarriage :data="marriageData" />
</template>
<template v-if="lawsuitData">
<div id="lawsuit" class="title">
涉诉案件
</div>
<CLawsuit :data="lawsuitData" />
</template>
<template v-if="badData">
<div id="bad" class="title">
不良风险评估
</div>
<CBad :data="badData" />
</template>
<template v-if="entData">
<div id="ent" class="title">
关联企业
</div>
<CRelatedEnterprises :data="entData" />
</template>
<template v-if="specialData">
<div id="special" class="title">
异常名单
</div>
<CSpecialList :data="specialData" />
</template>
<template v-if="bankLoanBehavior">
<div id="loan" class="title">
借贷记录
</div>
<CBankLoanBehavior :data="bankLoanBehavior" />
</template>
<template v-if="bankLoanApplicationData">
<div id="netloan" class="title">
贷款申请记录
</div>
<CBankLoanApplication :data="bankLoanApplicationData" />
</template>
<view class="card">
<view>
<view class="text-blue-500 font-bold">
报告说明
</view>
<view>本报告的数据由用户本人明确授权后我们才向相关合法存有用户个人数据的机构调取本报告相关内容本平台只做大数据的获取与分析仅向用户个人展示参考</view><p> &nbsp; &nbsp; 报告有效期<strong>30</strong>过期自动删除 </p><p> &nbsp; &nbsp; 若您的数据不全面可能是数据具有延迟性或者合作信息机构未获取到您的数据若数据有错误请联系客服</p>
</view>
</view>
</div>
</template>
</div>
</template>
<style lang="scss" scoped>
</style>
<route lang="json">
{
"layout": "page",
"title": "报告示例"
}
</route>

View File

@@ -1,41 +0,0 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
const feature = ref(null)
const token = ref(null)
const webviewSrc = ref('')
onLoad((option) => {
if (option.feature) {
feature.value = option.feature
}
token.value = uni.getStorageSync('token') || ''
const baseUrl = 'https://app.quannengcha.com/example'
webviewSrc.value = `${baseUrl}?feature=${encodeURIComponent(feature.value)}&token=${encodeURIComponent(token.value)}`
})
</script>
<template>
<view>
<!-- 使用动态构造的 WebView src -->
<web-view :webview-styles="webviewStyles" :src="webviewSrc" />
</view>
</template>
<style lang="scss" scoped>
</style>
<route lang="json">
{
"layout": "page",
"title": "示例报告"
}
</route>

View File

@@ -1,65 +1,166 @@
<script setup>
import indexIcon1 from '/static/image/index_icon_1.png'
import indexIcon2 from '/static/image/index_icon_2.png'
import indexIcon3 from '/static/image/index_icon_3.png'
import indexIcon4 from '/static/image/index_icon_4.png'
import indexIcon5 from '/static/image/index_icon_5.png'
import indexIcon6 from '/static/image/index_icon_6.png'
import indexIcon7 from '/static/image/index_icon_7.png'
// 引入 WebView 插件
// @ts-ignore
import { urlLaunch } from '@/uni_modules/lz-url_launch';
const services = ref(
[
{
title: '个人风险',
name: 'riskassessment',
subtitle: '一查全知',
bg: indexIcon2,
bgColor: 'bg-indigo-400',
position: 'rounded-tl-[35px] rounded-bl-[35px] rounded-tr-lg rounded-br-lg'
},
{
title: '婚恋风险',
name: 'marriage',
subtitle: '查婚姻状态让爱无忧',
bg: indexIcon1,
bgColor: ' bg-pink-400 ',
position: 'rounded-tr-[35px] rounded-br-[35px] rounded-tl-lg rounded-bl-lg'
},
{
title: '家政服务',
name: 'homeservice',
subtitle: '用人有保障',
bg: indexIcon3,
bgColor: ' bg-teal-500 ',
position: 'rounded-tl-[35px] rounded-bl-[35px] rounded-tr-lg rounded-br-lg'
},
{
title: '租赁风险',
name: 'rentalinfo',
subtitle: '一查明了',
bg: indexIcon4,
bgColor: ' bg-sky-500 ',
position: 'rounded-tl-[35px] rounded-bl-[35px] rounded-tr-lg rounded-br-lg'
},
{
title: '企业报告',
name: 'companyinfo',
subtitle: '合作更安心',
bg: indexIcon5,
bgColor: ' bg-blue-400 ',
position: 'rounded-tr-[35px] rounded-br-[35px] rounded-tl-lg rounded-bl-lg'
},
{
title: '人事背调',
name: 'backgroundcheck',
subtitle: '招聘有保障,选人更放心',
bg: indexIcon6,
bgColor: ' bg-orange-400 ',
position: 'rounded-tl-[35px] rounded-bl-[35px] rounded-tr-lg rounded-br-lg'
},
{
title: '贷前背调',
name: 'preloanbackgroundcheck',
subtitle: '招聘有保障,选人更放心',
bg: indexIcon7,
bgColor: ' bg-orange-400 ',
position: 'rounded-tr-[35px] rounded-br-[35px] rounded-tl-lg rounded-bl-lg'
},
]
)
function toInquire(name) {
uni.navigateTo({
url: `/pages/inquire?feature=${name}`,
})
// 使用服务名称构建URL
console.log('使用服务:', name);
// 判断环境,在 App 环境中使用 UTS 插件打开,非 App 环境使用普通导航
try {
// 构建服务的URL
urlLaunch(`https://www.quannengcha.com/inquire/${name}`)
} catch (error) {
console.error('打开URL失败:', error);
}
}
const services = ref([
{ title: '个人风险', name: 'riskassessment', subtitle: '一查全知', bg: '/static/image/index_icon_2.png', bgColor: 'bg-indigo-400', position: 'rounded-tl-[35px] rounded-bl-[35px] rounded-tr-lg rounded-br-lg' },
{ title: '婚恋风险', name: 'marriage', subtitle: '查婚姻状态让爱无忧', bg: '/static/image/index_icon_1.png', bgColor: ' bg-pink-400 ', position: 'rounded-tr-[35px] rounded-br-[35px] rounded-tl-lg rounded-bl-lg' },
{ title: '家政服务', name: 'homeservice', subtitle: '用人有保障', bg: '/static/image/index_icon_3.png', bgColor: ' bg-teal-500 ', position: 'rounded-tl-[35px] rounded-bl-[35px] rounded-tr-lg rounded-br-lg' },
{ title: '租赁风险', name: 'rentalinfo', subtitle: '一查明了', bg: '/static/image/index_icon_4.png', bgColor: ' bg-sky-500 ', position: 'rounded-tl-[35px] rounded-bl-[35px] rounded-tr-lg rounded-br-lg' },
{ title: '企业报告', name: 'companyinfo', subtitle: '合作更安心', bg: '/static/image/index_icon_5.png', bgColor: ' bg-blue-400 ', position: 'rounded-tr-[35px] rounded-br-[35px] rounded-tl-lg rounded-bl-lg' },
{ title: '人事背调', name: 'backgroundcheck', subtitle: '招聘有保障,选人更放心', bg: '/static/image/index_icon_6.png', bgColor: ' bg-orange-400 ', position: 'rounded-[35px] col-span-2' },
])
const noticeText = ref([])
function toHistory() {
uni.navigateTo({
url: '/pages/queryHistory',
})
}
function toInvitation() {
uni.navigateTo({
url: '/pages/invitation',
})
}
function toPromote() {
uni.navigateTo({
url: '/pages/promote',
})
}
function toHelp() {
uni.navigateTo({
url: '/pages/help',
})
}
</script>
<template>
<view class="box-border min-h-screen from-blue-100 to-white bg-gradient-to-b">
<view class="box-border">
<view class="relative h-[190px]">
<image class="h-full w-full" src="/static/image/banner2.png" />
<image
class="absolute bottom-[-70px] right-0 w-38"
src="/static/image/banner_a.png"
mode="aspectFit"
/>
<image class="absolute bottom-[-70px] right-0 w-38" src="/static/image/banner_a.png" mode="aspectFit" />
</view>
<view class="mt-4">
<view class="flex items-center justify-around gap-2 px-4 pb-1">
<view class="" @click="toPromote">
<view
class="h-12 w-12 p-2 bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
<image src="/static/image/icon_tg.svg" alt="直推报告" class="w-12 h-12" mode="aspectFit" />
</view>
<view class="text-center mt-1 font-bold">直推报告</view>
</view>
<view class="" @click="toInvitation">
<view
class="h-12 w-12 p-2 bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
<image src="/static/image/icon_xj.svg" alt="邀请下级" class="w-12 h-12" mode="aspectFit" />
</view>
<view class="text-center mt-1 font-bold">邀请下级</view>
</view>
<view class="" @click="toHelp">
<view
class="h-12 w-12 p-2 bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
<image src="/static/image/icon_bz.svg" alt="帮助中心" class="w-12 h-12" mode="aspectFit" />
</view>
<view class="text-center mt-1 font-bold">帮助中心</view>
</view>
<view class="" @click="toHistory">
<view
class="h-12 w-12 p-2 bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
<image src="/static/image/icon_bg.svg" alt="我的报告" class="w-12 h-12" mode="aspectFit" />
</view>
<view class="text-center mt-1 font-bold">我的报告</view>
</view>
</view>
</view>
<view class="relative p-4 pb-4 pt-2">
<view class="mb-1 flex items-center">
<view class="flex-shrink-0 pl-2 font-bold">
在线信息
</view>
<wd-notice-bar
:text="noticeText" direction="vertical" :delay="5" color="#4c4c4c"
background-color="#00000000"
/>
</view>
<view class="grid grid-cols-2 gap-3">
<template v-for="(service, index) in services" :key="index">
<view
class="relative flex flex-col px-4 py-2 shadow-lg" :class="[
service.position,
service.bgColor,
service.title === '婚恋风险' ? 'row-span-2' : '',
]" :style="`background: url(${service.bg}) no-repeat; background-size: cover; background-position: center;`"
@click="toInquire(service.name)"
>
<view class="relative flex flex-col px-4 py-2 shadow-lg " :class="[
service.position,
service.bgColor,
service.title === '婚恋风险' ? 'row-span-2' : '',
]"
:style="`background: url(${service.bg}) no-repeat; background-size: cover; background-position: center;`"
@click="toInquire(service.name)">
<view class="min-h-18 flex flex-col items-start px-1">
<view class="mt-1 max-w-max text-left text-gray-600 font-bold">
{{ service.title }}
</view>
<view class="max-w-max text-left text-xs text-gray-600">
<rich-text :nodes="service.subtitle" />
</view>
<view class="mt-2 rounded-2xl px-2 text-xs text-white" :class="[service.bgColor]">
GO >
</view>
@@ -67,15 +168,9 @@ function toHistory() {
</view>
</template>
</view>
<view
class="mt-4 box-border h-14 w-full flex items-center rounded-xl bg-white px-4 text-gray-700 shadow-xl"
@click="toHistory"
>
<image
class="mr-4 h-10 w-10"
src="/static/image/bg_icon.png"
mode="widthFix"
/>
<view class="mt-4 box-border h-14 w-full flex items-center rounded-xl bg-white px-4 text-gray-700 shadow-xl"
@click="toHistory">
<image class="mr-4 h-10 w-10" src="/static/image/bg_icon.png" mode="widthFix" />
<view class="">
<view class="font-bold">
我的历史查询记录
@@ -86,8 +181,7 @@ function toHistory() {
</view>
</view>
<view
class="mb-16 mt-6 h-12 w-full flex items-center justify-center rounded-3xl from-blue-500 to-sky-400 bg-gradient-to-b text-center text-lg text-white line-height-12 shadow-xl"
>
class="mb-16 mt-6 h-12 w-full flex items-center justify-center rounded-3xl from-blue-500 to-sky-400 bg-gradient-to-b text-center text-lg text-white line-height-12 shadow-xl">
<view>全能查邀您共赢共享数据新价值</view>
</view>
</view>
@@ -104,8 +198,10 @@ function toHistory() {
}
</style>
<route type="home" lang="json">
{
"layout": "home"
}
</route>
<route type="home" lang="json">{
"layout": "home",
"style": {
"navigationBarTextStyle": "white",
"transparentTitle": "always"
}
}</route>

View File

@@ -1,294 +0,0 @@
<script setup>
import { aesEncrypt } from '@/utils/crypto'
import { getCode, getProduct, queryMarriage, querybackgroundCheck, querycompanyInfo, queryhomeService, querypreLoanBackgroundCheck, queryrentalInfo, queryriskAssessment } from '@/api/apis'
const name = ref('')
const idCard = ref('')
const phoneNumber = ref('')
const verificationCode = ref('')
const agreeToTerms = ref(false)
const isCountingDown = ref(false)
const countdown = ref(60)
const feature = ref('')
const timer = null
const featureData = ref({})
const services = reactive([
{ title: '个人风险报告', name: 'riskassessment', subtitle: '一查全知', bg: '/static/image/index_icon_2.png', bgColor: 'bg-indigo-400', api: queryriskAssessment },
{ title: '婚恋报告', name: 'marriage', subtitle: '查婚姻状态让爱无忧', bg: '/static/image/index_icon_1.png', bgColor: ' bg-pink-400 ', api: queryMarriage },
{ title: '家政服务报告', name: 'homeservice', subtitle: '用人有保障', bg: '/static/image/index_icon_3.png', bgColor: ' bg-teal-500 ', api: queryhomeService },
{ title: '租赁服务报告', name: 'rentalinfo', subtitle: '一查明了', bg: '/static/image/index_icon_4.png', bgColor: ' bg-sky-500 ', api: queryrentalInfo },
{ title: '贷前调查报告', name: 'preloanbackgroundcheck', subtitle: '放心借贷', bg: '/static/image/index_icon_7.png', bgColor: ' bg-red-400 ', api: querypreLoanBackgroundCheck },
{ title: '人事背调报告', name: 'backgroundcheck', subtitle: '选人更放心', bg: '/static/image/index_icon_6.png', bgColor: ' bg-orange-400 ', api: querybackgroundCheck },
{ title: '企业报告', name: 'companyinfo', subtitle: '合作更安心', bg: '/static/image/index_icon_5.png', bgColor: ' bg-blue-400 ', api: querycompanyInfo },
])
const service = ref({})
onLoad((options) => {
console.log('options', options)
if (options.feature) {
feature.value = options.feature
}
else {
feature.value = 'marrige'
}
getService()
getProduct(feature.value).then((res) => {
if (res.code === 200) {
featureData.value = res.data
}
})
})
const isPhoneNumberValid = computed(() => {
return /^1[3-9]\d{9}$/.test(phoneNumber.value)
})
const isIdCardValid = computed(() => /^\d{17}[\dX]$/i.test(idCard.value))
function handleSubmit() {
if (!agreeToTerms.value) {
uni.showToast({ title: '请阅读并同意用户协议和隐私政策', icon: 'none' })
return
}
if (!name.value) {
uni.showToast({ title: '请输入姓名', icon: 'none' })
return
}
if (!isPhoneNumberValid.value) {
uni.showToast({ title: '请输入有效的手机号', icon: 'none' })
return
}
if (!isIdCardValid.value) {
uni.showToast({ title: '请输入有效的身份证号码', icon: 'none' })
return
}
if (!verificationCode.value) {
uni.showToast({ title: '请输入验证码', icon: 'none' })
return
}
submit()
}
function getService() {
for (const i of services) {
if (i.name === feature.value) {
service.value = i
}
}
}
function sendVerificationCode() {
if (isCountingDown.value || !isPhoneNumberValid.value)
return
if (!isPhoneNumberValid.value) {
uni.showToast({ title: '请输入有效的手机号', icon: 'none' })
return
}
getCode({
mobile: phoneNumber.value,
actionType: 'query',
}).then((res) => {
if (res.code === 200) {
uni.showToast({ title: '获取成功', icon: 'none' })
startCountdown()
}
})
}
function startCountdown() {
isCountingDown.value = true
countdown.value = 60
timer = setInterval(() => {
if (countdown.value > 0) {
countdown.value--
}
else {
clearInterval(timer)
isCountingDown.value = false
}
}, 1000)
}
function toExample() {
uni.navigateTo({
url: `/pages/example?feature=${feature.value}`,
})
}
function submit() {
const req = {
name: name.value,
id_card: idCard.value,
mobile: phoneNumber.value,
code: verificationCode.value,
}
const data = JSON.stringify(req)
const encodeData = aesEncrypt(data, 'ff83609b2b24fc73196aac3d3dfb874f')
service.value.api({ data: encodeData }).then((res) => {
if (res.code === 200) {
uni.navigateTo({
url: `/pages/authorization?id=${res.data.id}`,
})
}
})
}
function toUserAgreement() {
uni.navigateTo({
url: '/pages/userAgreement',
})
}
function toPrivacyPolicy() {
uni.navigateTo({
url: '/pages/privacyPolicy',
})
}
onUnmounted(() => {
if (timer) {
clearInterval(timer)
}
})
</script>
<template>
<view class="inquire-bg min-h-screen rounded-lg p-6 shadow-lg">
<view class="mb-6 text-center text-blue-800 font-extrabold">
<view class="text-blue-600">
<text class="text-2xl font-bold">
{{ service.title }}
</text>
</view>
</view>
<view class="card-p-0 px-4 py-6">
<view class="mb-4 text-xl text-gray-800 font-semibold">
基本信息
</view>
<wd-input
v-model="name" label="姓名" type="text" label-width="60px" placeholder="请输入正确的姓名"
class="mb-6 border-b border-gray-200 border-b-solid"
/>
<wd-input
v-model="idCard" label="身份证号" label-width="60px" placeholder="请输入准确的身份证号码"
class="mb-6 border-b border-gray-200 border-b-solid"
/>
<wd-input
v-model="phoneNumber" label="手机号" type="tel" label-width="60px" placeholder="输入手机号"
class="mb-6 border-b border-gray-200 border-b-solid"
/>
<view class="mb-6 flex items-center">
<wd-input
v-model="verificationCode" label="验证码" type="number" label-width="60px" placeholder="输入验证码"
class="flex-1 border-b border-gray-200 border-b-solid"
/>
<view
class="ml-2 flex-shrink-0 rounded-lg border-none px-2 py-2 text-sm font-bold outline-none ring-none transition duration-300"
:class="isCountingDown || !isPhoneNumberValid ? 'cursor-not-allowed bg-gray-300 text-gray-500' : 'bg-blue-500 text-white hover:bg-blue-600'"
@click="sendVerificationCode"
>
{{ isCountingDown ? `${countdown}s重新获取` : '获取验证码' }}
</view>
</view>
<view class="mb-6 flex items-center">
<wd-checkbox v-model="agreeToTerms" />
<view class="ml-1 text-xs text-gray-400">
我已阅读并同意<text class="text-blue-500 hover:underline" @click="toUserAgreement">
用户协议
</text><text class="text-blue-500 hover:underline" @click="toPrivacyPolicy">
隐私政策
</text>
</view>
</view>
<view class="flex">
<wd-button
custom-style="border-top-right-radius: 0;
border-bottom-right-radius: 0;" plain class="w-10 py-3 text-lg font-bold" @click="toExample"
>
示例报告
</wd-button>
<wd-button
custom-style="border-top-left-radius: 0;
border-bottom-left-radius: 0;" type="primary" class="flex-1 py-3 text-lg font-bold" @click="handleSubmit"
>
立即查询 {{ featureData.sell_price }}
</wd-button>
</view>
</view>
<wd-divider class="my-4" />
<view class="card">
<!-- 报告标题 -->
<view class="mb-6 text-xl text-gray-800 font-bold">
{{ featureData.product_name }}
</view>
<!-- 报告介绍 -->
<view class="mb-4 text-gray-600 leading-relaxed">
{{ featureData.description }}
</view>
<!-- 报价信息 -->
<view class="mb-6 flex items-center justify-between">
<view class="text-lg text-gray-500">
价格
</view>
<view class="text-lg text-blue-600 font-semibold">
¥{{ featureData.sell_price }}
</view>
</view>
<!-- 报告主要内容 -->
<view class="mb-4 text-lg text-gray-800 font-semibold">
报告主要内容
</view>
<view class="grid grid-cols-2 gap-4">
<view
v-for="(feature, index) in featureData.features"
:key="feature.id"
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium"
:class="[
(Math.floor(index / 2) + (index % 2)) % 2 === 0
? 'bg-gradient-to-r from-blue-200 via-blue-200 to-blue-100'
: 'bg-gradient-to-r from-sky-200 via-sky-200 to-sky-100',
]"
>
{{ feature.name }}
</view>
</view>
</view>
</view>
</template>
<style scoped>
.icon-company,
.icon-transaction,
.icon-judicial,
.icon-penalty {
font-size: 2rem;
}
.inquire-bg {
background: url("/static/image/bg_2.png") no-repeat;
position: relative;
}
.inquire-bg::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.4);
/* 使用白色的半透明覆盖层0.5 可调整为其他透明度值 */
z-index: 1;
}
.inquire-bg>* {
position: relative;
z-index: 2;
/* 确保子元素在覆盖层之上 */
}
</style>
<route lang="json">
{
"layout": "page",
"title": "报告查询"
}
</route>

51
src/pages/invitation.vue Normal file
View File

@@ -0,0 +1,51 @@
<template>
<view>
<image src="/static/image/invitation.png" alt="邀请下级" mode="widthFix" class="w-full" />
<view @click="showQRcode = true"
class="bg-gradient-to-t from-orange-500 to-orange-300 fixed bottom-0 h-12 w-full shadow-xl text-white rounded-t-xl flex items-center justify-center font-bold">
立即邀请好友
</view>
<QRcode v-model:show="showQRcode" mode="invitation" :linkIdentifier="linkIdentifier" />
</view>
</template>
<script setup>
import { ref, onBeforeMount } from 'vue'
import { aesEncrypt } from "@/utils/crypto"
import QRcode from '@/components/QRcode.vue'
const showQRcode = ref(false)
const linkIdentifier = ref("")
const mobile = ref("")
const agentID = ref("")
onBeforeMount(() => {
// 从UniApp缓存获取用户信息
const userInfo = uni.getStorageSync('userInfo') || {}
mobile.value = userInfo.mobile || ''
agentID.value = userInfo.agentID || ''
encryptIdentifire(agentID.value, mobile.value)
})
const encryptIdentifire = (agentID, mobile) => {
const linkIdentifierJSON = {
agentID,
mobile
}
const linkIdentifierStr = JSON.stringify(linkIdentifierJSON)
const encodeData = aesEncrypt(linkIdentifierStr, "8e3e7a2f60edb49221e953b9c029ed10")
linkIdentifier.value = encodeURIComponent(encodeData)
}
</script>
<style>
/* 自定义样式 */
</style>
<route type="page" lang="json">{
"layout": "page",
"title": "邀请下级",
"auth": true,
"agent": true
}</route>

View File

@@ -0,0 +1,199 @@
<template>
<view class="min-h-screen bg-[#D1D6FF]">
<image src="/static/image/invitation_agent_apply.png" alt="邀请代理申请" mode="widthFix" class="w-full" />
<!-- 统一状态处理容器 -->
<view class="flex flex-col items-center justify-center">
<!-- 审核中状态 -->
<view v-if="displayStatus === 0" class="text-center">
<text class="text-xs text-gray-500 block">您的申请正在审核中</text>
<view class="bg-gray-200 p-1 rounded-3xl shadow-xl mt-1">
<view class="text-xl font-bold px-8 py-2 bg-gray-400 text-white rounded-3xl shadow-lg cursor-not-allowed">
审核进行中
</view>
</view>
</view>
<!-- 审核通过状态 -->
<view v-if="displayStatus === 1" class="text-center">
<text class="text-xs text-gray-500 block">您已成为认证代理方</text>
<view class="bg-green-100 p-1 rounded-3xl shadow-xl mt-1" @click="goToHome">
<view
class="text-xl font-bold px-8 py-2 bg-gradient-to-t from-green-500 to-green-300 text-white rounded-3xl shadow-lg cursor-pointer">
进入应用首页
</view>
</view>
</view>
<!-- 审核未通过状态 -->
<view v-if="displayStatus === 2" class="text-center">
<text class="text-xs text-red-500 block">审核未通过请重新提交</text>
<view class="bg-red-100 p-1 rounded-3xl shadow-xl mt-1" @click="agentApply">
<view
class="text-xl font-bold px-8 py-2 bg-gradient-to-t from-red-500 to-red-300 text-white rounded-3xl shadow-lg cursor-pointer">
重新提交申请
</view>
</view>
</view>
<!-- 未申请状态包含邀请状态 -->
<view v-if="displayStatus === 3" class="text-center">
<text class="text-xs text-gray-500 block">{{ isSelf ? '立即申请成为代理人' : '邀您注册代理人' }}</text>
<view class="bg-gray-100 p-1 rounded-3xl shadow-xl mt-1" @click="agentApply">
<view
class="text-xl font-bold px-8 py-2 bg-gradient-to-t from-blue-500 to-blue-300 text-white rounded-3xl shadow-lg cursor-pointer">
立即成为代理方
</view>
</view>
</view>
</view>
<AgentApplicationForm v-model:show="showApplyPopup" @submit="submitApplication" @close="showApplyPopup = false"
:ancestor="ancestor" />
</view>
</template>
<script setup>
import { ref, computed, onBeforeMount } from 'vue'
import { getAgentInfo, applyAgent } from '@/apis/agent'
import AgentApplicationForm from '@/components/AgentApplicationForm.vue'
const showApplyPopup = ref(false)
const status = ref(3) // 默认为未申请状态
const ancestor = ref("")
const isSelf = ref(true)
let intervalId = null // 保存定时器 ID
// 计算显示状态当isSelf为false时强制显示为3
const displayStatus = computed(() => {
return !isSelf.value ? 3 : status.value
})
// 打开申请表单
const agentApply = () => {
showApplyPopup.value = true
}
// 跳转到首页
const goToHome = () => {
clearInterval(intervalId)
uni.switchTab({
url: '/pages/index'
})
}
const getAgentInformation = async () => {
const token = uni.getStorageSync("token")
if (!token) {
return
}
try {
const res = await getAgentInfo()
if (res.code === 200 && res.data) {
// 将代理信息存入缓存
uni.setStorageSync("agentInfo", {
level: res.data.level,
isAgent: res.data.is_agent, // 判断是否是代理
status: res.data.status, // 获取代理状态 0=待审核1=审核通过2=审核未通过3=未申请
agentID: res.data.agent_id,
mobile: res.data.mobile
})
status.value = res.data.status
console.log('代理信息已获取并存入缓存')
}
} catch (error) {
console.error('获取代理信息失败', error)
}
}
// 提交代理申请
const submitApplication = async (formData) => {
try {
const { region, mobile, wechat_id, code } = formData
let postData = {
region,
mobile,
wechat_id,
code,
}
if (!isSelf.value) {
postData.ancestor = ancestor.value
}
const res = await applyAgent(postData)
if (res.code === 200) {
showApplyPopup.value = false
uni.showToast({
title: "已提交申请",
icon: 'success'
})
if (res.data.accessToken) {
uni.setStorageSync('token', res.data.accessToken)
uni.setStorageSync('refreshAfter', res.data.refreshAfter)
uni.setStorageSync('accessExpire', res.data.accessExpire)
refreshAgentStatus()
}
} else {
uni.showToast({
title: res.msg || '申请失败',
icon: 'none'
})
}
} catch (error) {
uni.showToast({
title: '网络错误',
icon: 'none'
})
}
}
// 定时刷新代理状态
const refreshAgentStatus = () => {
if (status.value === 3) {
if (intervalId) clearInterval(intervalId)
intervalId = setInterval(() => {
if (status.value !== 3) {
clearInterval(intervalId)
intervalId = null
return
}
getAgentInformation()
}, 2000)
} else {
if (intervalId) {
clearInterval(intervalId)
intervalId = null
}
}
}
onLoad(() => {
const token = uni.getStorageSync('token')
if (token) {
// 从缓存中获取代理信息
const agentInfo = uni.getStorageSync('agentInfo')
if (agentInfo) {
status.value = agentInfo.status || 3
}
getAgentInformation()
}
})
// 页面卸载时清除定时器
onUnload(() => {
if (intervalId) {
clearInterval(intervalId)
intervalId = null
}
})
</script>
<route type="page" lang="json">{
"layout": "page",
"title": "代理申请",
"auth": true
}</route>

View File

@@ -1,6 +1,6 @@
<script setup>
import { getCode, login } from '@/api/apis'
import { getCode, login, getUserInfo } from '@/api/apis'
import { getAgentInfo } from '@/apis/agent'
const phoneNumber = ref('')
const verificationCode = ref('')
const password = ref('')
@@ -72,10 +72,13 @@ function handleLogin() {
return
}
login({ mobile: phoneNumber.value, code: verificationCode.value }).then((res) => {
console.log('res.data.AccessToken', res.data.accessToken)
if (res.code === 200) {
uni.setStorageSync('token', res.data.accessToken)
uni.setStorageSync('refreshAfter', res.data.refreshAfter)
uni.setStorageSync('accessExpire', res.data.accessExpire)
uni.showToast({ title: '登录成功', icon: 'none' })
getUser()
getAgentInformation()
uni.reLaunch({
url: '/pages/index',
})
@@ -88,14 +91,50 @@ function handleLogin() {
function toUserAgreement() {
uni.navigateTo({
url: '/pages/userAgreement',
url: '/pages/agreement?type=user',
})
}
function toPrivacyPolicy() {
uni.navigateTo({
url: '/pages/privacyPolicy',
url: '/pages/agreement?type=privacy',
})
}
const getAgentInformation = async () => {
const token = uni.getStorageSync("token")
if (!token) {
return
}
try {
const res = await getAgentInfo()
if (res.code === 200 && res.data) {
// 将代理信息存入缓存
uni.setStorageSync("agentInfo", {
level: res.data.level,
isAgent: res.data.is_agent, // 判断是否是代理
status: res.data.status, // 获取代理状态 0=待审核1=审核通过2=审核未通过3=未申请
agentID: res.data.agent_id,
mobile: res.data.mobile
})
console.log('代理信息已获取并存入缓存')
}
} catch (error) {
console.error('获取代理信息失败', error)
}
}
const getUser = async () => {
const token = uni.getStorageSync("token")
if (!token) {
return
}
const res = await getUserInfo()
if (res.code === 200) {
console.log(res.data)
uni.setStorageSync("userInfo", res.data.userInfo)
}
}
onUnmounted(() => {
if (timer) {
clearInterval(timer)
@@ -107,47 +146,32 @@ onUnmounted(() => {
<view class="login px-8">
<view class="mb-8 pt-8 text-left">
<view class="flex flex-col items-center">
<image
class="h-18 w-18 rounded-full shadow"
src="/static/image/logo.png"
mode="scaleToFill"
/>
<image
class="mt-4 h-10"
src="/static/image/logo_title.png"
mode="aspectFit"
/>
<image class="h-18 w-18 rounded-full shadow" src="/static/image/logo.png" mode="scaleToFill" />
<image class="mt-4 h-10" src="/static/image/logo_title.png" mode="aspectFit" />
</view>
</view>
<view class="space-y-5">
<view class="input-container bg-blue-300/20" :class="[phoneFocused ? 'focused' : '']">
<input
v-model="phoneNumber" class="input-field" type="number" placeholder="请输入手机号" maxlength="11"
@focus="phoneFocused = true" @blur="phoneFocused = false"
>
<input v-model="phoneNumber" class="input-field" type="number" placeholder="请输入手机号" maxlength="11"
@focus="phoneFocused = true" @blur="phoneFocused = false">
</view>
<view v-if="!isPasswordLogin">
<view class="flex items-center justify-between">
<view class="input-container bg-blue-300/20" :class="[codeFocused ? 'focused' : '']">
<input
v-model="verificationCode" class="input-field" type="number" placeholder="请输入验证码" maxlength="6"
@focus="codeFocused = true" @blur="codeFocused = false"
>
<input v-model="verificationCode" class="input-field" type="number" placeholder="请输入验证码" maxlength="6"
@focus="codeFocused = true" @blur="codeFocused = false">
</view>
<view
class="ml-2 flex-shrink-0 rounded-lg px-4 py-2 text-sm font-bold transition duration-300 focus:outline-none"
:class="isCountingDown || !isPhoneNumberValid ? 'cursor-not-allowed bg-gray-300 text-gray-500' : 'bg-blue-500 text-white hover:bg-blue-600'"
@click="sendVerificationCode"
>
@click="sendVerificationCode">
{{ isCountingDown ? `${countdown}s重新获取` : '获取验证码' }}
</view>
</view>
</view>
<view v-if="isPasswordLogin" class="input-container" :class="[passwordFocused ? 'focused' : '']">
<input
v-model="password" class="input-field" type="password" placeholder="请输入密码"
@focus="passwordFocused = true" @blur="passwordFocused = false"
>
<input v-model="password" class="input-field" type="password" placeholder="请输入密码"
@focus="passwordFocused = true" @blur="passwordFocused = false">
</view>
<view class="flex items-start space-x-2">
<wd-checkbox v-model="isAgreed" class="mt-1" />
@@ -165,17 +189,15 @@ onUnmounted(() => {
</view>
<button
class="mt-20 block w-full flex-shrink-0 rounded-full bg-blue-500 py-3 text-lg text-white font-bold transition duration-300"
@click="handleLogin"
>
@click="handleLogin">
登录
</button>
</view>
</template>
<style scoped>
.login{
.login {}
}
.input-container {
border: 2px solid rgba(125, 211, 252, 0.0);
border-radius: 1rem;
@@ -195,9 +217,7 @@ onUnmounted(() => {
}
</style>
<route lang="json">
{
<route lang="json">{
"layout": "login",
"title": "登录"
}
</route>
}</route>

View File

@@ -1,125 +1,246 @@
<script setup>
import { getUserInfo } from '@/api/apis'
const userName = ref('点击登录')
const userAvatar = ref('https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180')
const isLoggedIn = ref(false)
const features = ref([
{ title: '我的报告', icon: 'list', action: () => toHistory() },
{ title: '联系客服', icon: 'service', action: () => toService() },
{ title: '用户协议', icon: 'file', action: () => toUserAgreement() },
{ title: '退出登录', icon: 'logout', action: () => handleLogout() },
])
function toHistory() {
uni.navigateTo({
url: '/pages/queryHistory',
})
}
function toUserAgreement() {
uni.navigateTo({
url: '/pages/userAgreement',
})
}
function redirectToLogin() {
uni.reLaunch({ url: '/pages/login' }) // 使用 uni-app 路由跳转到登录页
}
function handleLogout() {
uni.removeStorageSync('token')
isLoggedIn.value = false
userName.value = '点击登录'
userAvatar.value = 'https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180'
}
function toService() {
uni.navigateTo({
url: '/pages/service',
})
}
async function fetchUserInfo() {
try {
// 假设通过 API 获取用户信息
getUserInfo().then((res) => {
if (res.code === 200) {
console.log('res', res)
const userinfo = res.data.userInfo
userName.value = userinfo.nickName || ''
userAvatar.value = userinfo.userAvatar || 'https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180'
isLoggedIn.value = true
}
})
}
catch (error) {
console.error('获取用户信息失败', error)
}
}
const safeAreaTop = ref(0)
onMounted(() => {
const token = uni.getStorageSync('token')
if (token) {
isLoggedIn.value = true
fetchUserInfo()
}
else {
isLoggedIn.value = false
}
uni.getSystemInfo({
success: (res) => {
if (res.safeArea) {
safeAreaTop.value = res.safeArea.top
}
},
})
})
</script>
<template>
<view
class="box-border min-h-screen from-blue-100 to-white bg-gradient-to-b" style="paddingTop:44px"
>
<view class="flex flex-col p-4">
<view class="profile-section mb-4 flex items-center gap-4 rounded-md bg-white p-4 shadow-md" @click="!isLoggedIn ? redirectToLogin() : null">
<wd-img :src="userAvatar" round width="100" height="100" />
<view>
<h2 class="text-lg font-bold">
{{ isLoggedIn ? userName : '点击登录' }}
</h2>
<view class="safe-area-top box-border min-h-screen">
<view class="flex flex-col p-4 space-y-6">
<!-- 用户信息卡片 -->
<view
class="profile-section group relative flex items-center gap-4 rounded-xl bg-white p-6 shadow-lg transition-all hover:shadow-xl"
@click="!isLoggedIn ? redirectToLogin() : null">
<view class="relative">
<!-- 头像容器添加overflow-hidden解决边框问题 -->
<view class="flex items-center justify-center overflow-hidden rounded-full p-0.5"
:class="levelGradient.border">
<image :src="userAvatar || headShot" alt="User Avatar" class="h-24 w-24 rounded-full border-4 border-white">
</image>
</view>
<!-- 代理标识 -->
<view v-if="isAgent" class="absolute -bottom-2 -right-2">
<view class="flex items-center justify-center rounded-full px-3 py-1 text-xs font-bold text-white shadow-sm"
:class="levelGradient.badge">
{{ levelNames[level] }}
</view>
</view>
</view>
<view class="space-y-1">
<view class="text-2xl font-bold text-gray-800">
{{ isLoggedIn ? maskName(userName) : '点击登录' }}
</view>
<view v-if="isAgent" class="text-sm font-medium" :class="levelGradient.text">
🎖 {{ levelText[level] }}
</view>
</view>
</view>
<VipBanner v-if="isAgent && level === 'normal'" />
<!-- 功能菜单 -->
<view class="features-section space-y-3">
<template v-if="isAgent && ['VIP', 'SVIP'].includes(level)">
<button
class="feature-item bg-gradient-to-r from-purple-200/80 to-pink-200/80 hover:from-purple-300/80 hover:to-pink-300/80 text-purple-700"
@click="toVipConfig">
代理报告配置
</button>
</template>
<Wdviewider />
<view class="features-section flex flex-col gap-2">
<WdCell
v-for="(feature, index) in features"
:key="index"
:title="feature.title"
:icon="feature.icon"
class="feature-item rounded-md bg-white p-3 shadow-sm"
clickable
@click="feature.action"
/>
<button class="feature-item hover:bg-blue-50" @click="toHistory">
📃 我的报告
</button>
<button class="feature-item hover:bg-blue-50" @click="toUserAgreement">
📜 用户协议
</button>
<button class="feature-item hover:bg-blue-50" @click="toService">
💬 联系客服
</button>
<button class="feature-item hover:bg-red-50 text-red-600" @click="handleLogout">
退出登录
</button>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.profile-section {
@apply flex items-center gap-4 p-4 bg-white rounded-md shadow-md mb-4;
<script setup>
import { ref, computed, onBeforeMount } from 'vue'
import headShot from "@/static/image/head_shot.webp"
// 用户数据
const userName = ref('')
const userAvatar = ref('')
const isLoggedIn = ref(false)
// 代理数据
const isAgent = ref(false)
const level = ref('normal')
// 检查平台环境
onBeforeMount(() => {
// 从缓存获取用户信息
const token = uni.getStorageSync('token')
if (token) {
isLoggedIn.value = true
// 从缓存获取用户信息
const userInfo = uni.getStorageSync('userInfo')
console.log("userInfo", userInfo)
if (userInfo) {
userName.value = userInfo.nickName || '用户'
userAvatar.value = userInfo.avatar || ''
}
// 从缓存获取代理信息
const agentInfo = uni.getStorageSync('agentInfo')
if (agentInfo?.isAgent) {
isAgent.value = agentInfo.isAgent
level.value = agentInfo.level || 'normal'
}
}
})
const levelNames = {
normal: '普通代理',
VIP: 'VIP代理',
SVIP: 'SVIP代理'
}
.features-section {
@apply flex flex-col gap-2;
const levelText = {
normal: '基础代理特权',
VIP: '高级代理特权',
SVIP: '尊享代理特权'
}
const levelGradient = computed(() => ({
border: {
'normal': 'bg-green-300',
'VIP': 'bg-gradient-to-r from-yellow-400 to-amber-500',
'SVIP': 'bg-gradient-to-r from-purple-400 to-pink-400 shadow-[0_0_15px_rgba(163,51,200,0.2)]'
}[level.value],
badge: {
'normal': 'bg-green-500',
'VIP': 'bg-gradient-to-r from-yellow-500 to-amber-600',
'SVIP': 'bg-gradient-to-r from-purple-500 to-pink-500'
}[level.value],
text: {
'normal': 'text-green-600',
'VIP': 'text-amber-600',
'SVIP': 'text-purple-600'
}[level.value]
}))
function maskName(name) {
if (!name || name.length < 11) return name
return name.substring(0, 3) + "****" + name.substring(7)
}
function toHistory() {
uni.navigateTo({
url: '/pages/queryHistory'
})
}
function toUserAgreement() {
uni.navigateTo({
url: '/pages/agreement?type=user'
})
}
function redirectToLogin() {
uni.navigateTo({
url: '/pages/login'
})
}
function handleLogout() {
uni.removeStorageSync('token')
uni.removeStorageSync('refreshAfter')
uni.removeStorageSync('accessExpire')
uni.removeStorageSync('userInfo')
uni.removeStorageSync('agentInfo')
// 重置状态
isLoggedIn.value = false
userName.value = ''
userAvatar.value = ''
isAgent.value = false
level.value = 'normal'
uni.reLaunch({
url: '/pages/index'
})
}
function toService() {
// #ifdef APP-PLUS
plus.runtime.openURL('https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9')
// #endif
// #ifdef H5
window.location.href = 'https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9'
// #endif
// #ifdef MP
uni.setClipboardData({
data: 'https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9',
success: function () {
uni.showToast({
title: '客服链接已复制,请在浏览器中打开',
icon: 'none'
})
}
})
// #endif
}
function toVipConfig() {
uni.navigateTo({
url: '/pages/agentVipConfig'
})
}
</script>
<style scoped>
.profile-section {
background: linear-gradient(135deg, #ffffff 50%, rgba(236, 253, 245, 0.3));
border: 1px solid rgba(209, 213, 219, 0.2);
}
.profile-section .relative>view:first-child {
transition: all 0.3s ease;
}
.feature-item {
@apply bg-white p-3 rounded-md shadow-sm;
transition:
transform 0.2s ease,
background 0.3s ease,
box-shadow 0.3s ease;
display: flex;
width: 100%;
align-items: center;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
margin-right: 0.75rem;
border-radius: 0.75rem;
background-color: #ffffff;
padding: 1rem 1.5rem;
text-align: left;
color: #4b5563;
transition-property: all;
transition-duration: 300ms;
}
.feature-item:active {
transform: scale(1.02);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.border-gradient-to-r {
border-image: linear-gradient(to right, var(--tw-gradient-from), var(--tw-gradient-to)) 1;
}
.shadow-glow {
box-shadow: 0 0 8px rgba(163, 51, 200, 0.2);
}
</style>
<route lang="json">
{
"layout": "home"
}
</route>
<route lang="json">{
"layout": "home"
}</route>

View File

@@ -1,98 +0,0 @@
<script setup>
import { payment, queryProvisionalOrder } from '@/api/apis'
const selectedPaymentMethod = ref('alipay')
const id = ref(null)
const order = ref({
productName: '',
price: null,
})
function handlePayment() {
if (selectedPaymentMethod.value === 'alipay') {
payment({ id: id.value, pay_method: selectedPaymentMethod.value }).then((res) => {
if (res.code === 200) {
uni.requestPayment({
provider: 'alipay', // 支付宝
orderInfo: res.data.prepay_id, // 后台返回的orderInfo
success: () => {
handlePaySuccess(res.data.order_id)
},
fail: (err) => {
console.log('支付失败:', err)
},
})
}
})
}
}
function handlePaySuccess(orderID) {
uni.redirectTo({
url: `/pages/result?id=${orderID}`,
})
}
onLoad((option) => {
if (option.id) {
id.value = option.id
queryProvisionalOrder(option.id).then((res) => {
console.log('res', res)
if (res.code === 200) {
order.value.productName = res.data.product.product_name
order.value.price = res.data.product.sell_price
}
})
}
})
</script>
<template>
<view class="min-h-screen from-blue-200 via-sky-200 to-sky-100 bg-gradient-to-b p-6">
<view class="card">
<h1 class="mb-4 text-xl font-bold">
订单支付
</h1>
<view class="my-10 text-center">
<view class="text-2xl font-bold">
¥{{ order.price }}
</view>
<view class="text-gray-600">
{{ order.productName }}
</view>
</view>
<view class="mb-4">
<label class="mb-2 block text-sm text-gray-600">支付方式</label>
<wd-radio-group v-model="selectedPaymentMethod" shape="dot" size="large">
<view class="border-3 border-blue-500 rounded-lg border-solid px-4 py-2">
<wd-radio value="alipay">
<view class="flex" items-center>
<image
src="/static/image/alipay_icon.svg"
mode="aspectFit"
class="mr-1 h-5 w-5"
/> 支付宝
</view>
</wd-radio>
</view>
</wd-radio-group>
</view>
<button
class="w-full rounded-xl from-blue-500 via-blue-500 to-blue-400 bg-gradient-to-b px-4 py-2 text-white"
@click="handlePayment"
>
立即支付
</button>
</view>
</view>
</template>
<style scoped>
:deep(.wd-radio){
margin-top: 0;
}
</style>
<route lang="json">
{
"layout": "page",
"title": "全能查收款"
}
</route>

View File

@@ -1,164 +0,0 @@
<script setup>
import { iapPaymentCallback, payment, queryProvisionalOrder } from '@/api/apis'
const selectedPaymentMethod = ref('appleiap')
const id = ref(null)
const order = ref({
productName: '',
price: null,
})
async function handlePayment() {
try {
if (selectedPaymentMethod.value === 'appleiap') {
const paymentResponse = await payment({ id: id.value, pay_method: selectedPaymentMethod.value })
if (paymentResponse.code === 200) {
uni.showLoading({ title: '加载中' })
const productID = paymentResponse.data.prepay_id
const orderID = paymentResponse.data.order_id
const iapChannel = await getIapChannel()
const products = await requestProduct(iapChannel, [productID])
if (products.length > 0) {
const product = products[0]
uni.requestPayment({
provider: 'appleiap',
orderInfo: { productid: product.productid },
success: async (iapRes) => {
const callbackResponse = await iapPaymentCallback({
order_id: orderID,
transaction_receipt: iapRes.transactionReceipt,
})
if (callbackResponse.code === 200) {
handlePaySuccess(orderID)
}
else {
console.error('支付回调处理失败:', callbackResponse)
}
},
fail: (err) => {
console.error('支付失败:', err)
},
})
}
else {
console.error('未找到对应的产品信息')
}
}
else {
console.error('支付请求失败:', paymentResponse)
}
}
else {
console.error('未选择 Apple IAP 支付方式')
}
}
catch (error) {
console.error('支付流程中发生错误:', error)
}
finally {
uni.hideLoading()
}
}
async function getIapChannel() {
return new Promise((resolve, reject) => {
uni.showLoading({ title: '加载中' })
plus.payment.getChannels((channels) => {
const iapChannel = channels.find(channel => channel.id === 'appleiap')
if (iapChannel) {
resolve(iapChannel)
}
else {
reject(new Error('未找到 Apple IAP 支付通道'))
}
}, (error) => {
reject(new Error(`获取支付通道失败:${error.message}`))
})
})
}
async function requestProduct(iapChannel, productIds) {
return new Promise((resolve, reject) => {
uni.showLoading({ title: '加载中' })
console.log('请求的产品 ID 列表:', productIds)
iapChannel.requestOrder(productIds, (products) => {
resolve(products)
}, (error) => {
reject(new Error(`请求产品信息失败:${error.message}`))
})
})
}
function handlePaySuccess(orderID) {
uni.redirectTo({
url: `/pages/result?id=${orderID}`,
})
}
onLoad((option) => {
if (option.id) {
id.value = option.id
queryProvisionalOrder(option.id).then((res) => {
console.log('res', res)
if (res.code === 200) {
order.value.productName = res.data.product.product_name
order.value.price = res.data.product.sell_price
}
})
}
})
</script>
<template>
<view class="min-h-screen from-blue-200 via-sky-200 to-sky-100 bg-gradient-to-b p-6">
<view class="card">
<h1 class="mb-4 text-xl font-bold">
订单支付
</h1>
<view class="my-10 text-center">
<view class="text-2xl font-bold">
¥{{ order.price }}
</view>
<view class="text-gray-600">
{{ order.productName }}
</view>
</view>
<view class="mb-4">
<label class="mb-2 block text-sm text-gray-600">支付方式</label>
<wd-radio-group v-model="selectedPaymentMethod" shape="dot" size="large">
<view class="border-3 border-blue-500 rounded-lg border-solid px-4 py-2">
<wd-radio value="appleiap">
<view class="flex items-center">
<image
src="/static/image/apple.svg"
mode="aspectFit"
class="mr-1 h-5 w-5"
/> Apple Pay
</view>
</wd-radio>
</view>
</wd-radio-group>
</view>
<button
class="w-full rounded-xl from-blue-500 via-blue-500 to-blue-400 bg-gradient-to-b px-4 py-2 text-white"
@click="handlePayment"
>
立即支付
</button>
</view>
</view>
</template>
<style scoped>
:deep(.wd-radio) {
margin-top: 0;
}
</style>
<route lang="json">
{
"layout": "page",
"title": "全能查收款"
}
</route>

View File

@@ -1,22 +0,0 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" src="https://app.quannengcha.com/privacyPolicy" @message="handleMessage" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "隐私政策"
}
</route>

245
src/pages/promote.vue Normal file
View File

@@ -0,0 +1,245 @@
<template>
<view class="min-h-screen p-4 promote">
<view class="mb-4 card !bg-gradient-to-b from-orange-200 to-orange-200/80">
<view>
<text class="text-lg font-bold text-orange-500 block">直推用户查询</text>
<text class="font-bold text-orange-400 mt-1 block">自定义价格赚取差价</text>
</view>
<view class="mt-6">
<view class="mt-2 text-gray-600 bg-orange-100 rounded-xl px-4 py-2">
在下方 "自定义价格" 处选择报告类型设置客户查询价即可立即推广
</view>
</view>
</view>
<VipBanner />
<!-- 推广内容 -->
<view>
<view class="card mb-4">
<view>
<text class="text-xl font-semibold mb-2 block">生成推广码</text>
<wd-form :model="formData" ref="promotionForm">
<wd-cell-group border>
<!-- 报告类型 -->
<wd-picker label="报告类型" label-width="100px" v-model="formData.productType" :columns="[reportTypes]"
title="选择报告类型" prop="productType" placeholder="请选择报告类型" @confirm="onConfirmType"
:rules="[{ required: true, message: '请选择报告类型' }]" />
<!-- 定价 -->
<wd-input label="客户查询价" label-width="100px" v-model="formData.clientPrice" placeholder="请输入价格" readonly
clickable @click="showPricePicker = true" prop="clientPrice" suffix-icon="arrow-right"
:rules="[{ required: true, message: '请输入客户查询价' }]" />
</wd-cell-group>
<view class="flex items-center justify-between my-2">
<text class="text-sm text-gray-500">推广收益为 <text class="text-orange-500">{{ promotionRevenue }}</text>
</text>
<text class="text-sm text-gray-500">我的成本为 <text class="text-orange-500">{{ costPrice }}</text> </text>
</view>
</wd-form>
</view>
<view class="mt-6">
<button type="primary" block @click="generatePromotionCode">点击立即推广</button>
</view>
</view>
</view>
<PriceInputPopup v-model:show="showPricePicker" :default-price="formData.clientPrice"
:product-config="pickerProductConfig" @change="onPriceChange" />
<QRcode v-model:show="showQRcode" :linkIdentifier="linkIdentifier" />
</view>
</template>
<script setup>
import { getProductConfig, generatePromotionLink } from '@/apis/agent'
import PriceInputPopup from '@/components/PriceInputPopup.vue'
import VipBanner from '@/components/VipBanner.vue'
import QRcode from '@/components/QRcode.vue'
// 报告类型
const reportTypes = [
{ label: '人事背调', value: 'backgroundcheck', id: 1 },
{ label: '老板企业报告', value: 'companyinfo', id: 2 },
{ label: '家政风险', value: 'homeservice', id: 3 },
{ label: '婚恋风险', value: 'marriage', id: 4 },
{ label: '贷前背调', value: 'preloanbackgroundcheck', id: 5 },
{ label: '租赁风险', value: 'rentalrisk', id: 6 },
{ label: '个人风险', value: 'riskassessment', id: 7 }
]
// 状态管理
const promotionForm = ref(null)
const showPricePicker = ref(false)
const pickerProductConfig = ref(null)
const productConfig = ref(null)
const linkIdentifier = ref("")
const showQRcode = ref(false)
// 表单数据对象
const formData = ref({
productType: '',
clientPrice: null
})
// 计算成本价格
const costPrice = computed(() => {
if (!pickerProductConfig.value) return '0.00'
// 平台定价成本
let platformPricing = 0
platformPricing += pickerProductConfig.value.cost_price
if (formData.value.clientPrice > pickerProductConfig.value.p_pricing_standard) {
platformPricing += (formData.value.clientPrice - pickerProductConfig.value.p_pricing_standard) * pickerProductConfig.value.p_overpricing_ratio
}
if (pickerProductConfig.value.a_pricing_standard > platformPricing &&
pickerProductConfig.value.a_pricing_end > platformPricing &&
pickerProductConfig.value.a_overpricing_ratio > 0) {
if (formData.value.clientPrice > pickerProductConfig.value.a_pricing_standard) {
if (formData.value.clientPrice > pickerProductConfig.value.a_pricing_end) {
platformPricing += (pickerProductConfig.value.a_pricing_end - pickerProductConfig.value.a_pricing_standard) * pickerProductConfig.value.a_overpricing_ratio
} else {
platformPricing += (formData.value.clientPrice - pickerProductConfig.value.a_pricing_standard) * pickerProductConfig.value.a_overpricing_ratio
}
}
}
return safeTruncate(platformPricing)
})
// 计算推广收益
const promotionRevenue = computed(() => {
return safeTruncate(formData.value.clientPrice - costPrice.value)
})
// 安全截断数字保留2位小数
function safeTruncate(num, decimals = 2) {
if (isNaN(num) || !isFinite(num)) return "0.00"
const factor = 10 ** decimals
const scaled = Math.trunc(num * factor)
const truncated = scaled / factor
return truncated.toFixed(decimals)
}
// 生成推广码
const generatePromotionCode = async () => {
// 表单验证
try {
await promotionForm.value.validate()
} catch (e) {
return
}
try {
// 获取选中产品的完整信息
const reportType = reportTypes.find(item => item.value === formData.value.productType)
if (!reportType) {
uni.showToast({
title: '请选择有效的报告类型',
icon: 'none'
})
return
}
const res = await generatePromotionLink({
product: formData.value.productType,
price: formData.value.clientPrice
})
if (res.code === 200) {
linkIdentifier.value = res.data.link_identifier
showQRcode.value = true
} else {
uni.showToast({
title: res.msg || '生成推广码失败',
icon: 'none'
})
}
} catch (error) {
uni.showToast({
title: '网络错误',
icon: 'none'
})
}
}
// 选择类型
const selectProductType = (reportTypeValue) => {
const reportType = reportTypes.find(item => item.id === reportTypeValue || item.value === reportTypeValue)
if (!reportType) return
formData.value.productType = reportType.value
if (productConfig.value) {
for (let i of productConfig.value) {
if (i.product_id === reportType.id) {
pickerProductConfig.value = i
formData.value.clientPrice = i.p_pricing_standard.toString()
}
}
}
}
// 获取产品配置
const getPromoteConfig = async () => {
try {
const res = await getProductConfig()
if (res.code === 200) {
productConfig.value = res.data.AgentProductConfig
// 选择第一个报告类型
selectProductType(1) // 使用ID 1选择第一个报告类型
} else {
uni.showToast({
title: res.msg || '获取配置失败',
icon: 'none'
})
}
} catch (error) {
console.log(error)
uni.showToast({
title: '网络错误',
icon: 'none'
})
}
}
// 价格变更
const onPriceChange = (price) => {
formData.value.clientPrice = price
}
// 类型选择确认
const onConfirmType = (e) => {
// picker在单列模式下返回的是选中项的值
if (e && e.value && e.value.length > 0) {
const selectedValue = e.value[0]
selectProductType(selectedValue)
}
}
// 页面加载
onMounted(() => {
getPromoteConfig()
})
</script>
<style>
.card {
border-radius: 12px;
background-color: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
padding: 16px;
margin-bottom: 16px;
}
</style>
<route type="page" lang="json">{
"layout": "page",
"title": "推广",
"agent": true,
"auth": true
}</route>

View File

@@ -0,0 +1,144 @@
<template>
<view class="min-h-screen bg-gray-50">
<!-- 收益列表 -->
<uni-list :loading="loading" :loadmore="loadMoreStatus" @loadmore="onLoadMore">
<!-- 空状态提示 -->
<view v-if="!loading && list.length === 0" class="flex flex-col items-center justify-center py-16">
<image src="/static/image/empty.svg" mode="aspectFit" class="w-48 h-48 mb-4" />
<text class="text-gray-400 text-base">暂无直推报告</text>
</view>
<view v-for="(item, index) in list" :key="index" class="mx-4 my-2 bg-white rounded-lg p-4 shadow-sm">
<view class="flex justify-between items-center mb-2">
<text class="text-gray-500 text-sm">{{ item.create_time || '-' }}</text>
<text class="text-green-500 font-bold">+{{ item.amount.toFixed(2) }}</text>
</view>
<view class="flex items-center">
<text class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium"
:class="getReportTypeStyle(item.product_name)">
<text class="w-2 h-2 rounded-full mr-1 inline-block" :class="getDotColor(item.product_name)"></text>
{{ item.product_name }}
</text>
</view>
</view>
<!-- 加载更多/加载完成提示 -->
<uni-load-more :status="loadMoreStatus" />
</uni-list>
</view>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { getAgentCommission } from '@/apis/agent'
// 颜色配置(根据产品名称映射)
const typeColors = {
'老板企业报告': { bg: 'bg-blue-100', text: 'text-blue-800', dot: 'bg-blue-500' },
'人事背调': { bg: 'bg-green-100', text: 'text-green-800', dot: 'bg-green-500' },
'家政风险': { bg: 'bg-purple-100', text: 'text-purple-800', dot: 'bg-purple-500' },
'婚恋风险': { bg: 'bg-pink-100', text: 'text-pink-800', dot: 'bg-pink-500' },
'贷前背调': { bg: 'bg-orange-100', text: 'text-orange-800', dot: 'bg-orange-500' },
'租赁风险': { bg: 'bg-indigo-100', text: 'text-indigo-800', dot: 'bg-indigo-500' },
'个人风险': { bg: 'bg-red-100', text: 'text-red-800', dot: 'bg-red-500' },
// 默认类型
'default': { bg: 'bg-gray-100', text: 'text-gray-800', dot: 'bg-gray-500' }
}
const page = ref(1)
const pageSize = ref(10)
const total = ref(0)
const list = ref([])
const loading = ref(false)
const loadMoreStatus = ref('more') // 'more'|'loading'|'noMore'
// 获取颜色样式
const getReportTypeStyle = (name) => {
const color = typeColors[name] || typeColors.default
return `${color.bg} ${color.text}`
}
// 获取小圆点颜色
const getDotColor = (name) => {
return (typeColors[name] || typeColors.default).dot
}
// 加载更多数据
const onLoadMore = async () => {
if (loadMoreStatus.value === 'noMore') return
page.value++
await getData()
}
// 获取数据
const getData = async () => {
try {
loading.value = true
loadMoreStatus.value = 'loading'
const res = await getAgentCommission({
page: page.value,
page_size: pageSize.value
})
if (res.code === 200) {
// 首次加载
if (page.value === 1) {
list.value = res.data.list
total.value = res.data.total
} else {
// 分页加载
list.value.push(...res.data.list)
}
// 判断是否加载完成
if (list.value.length >= res.data.total || res.data.list.length < pageSize.value) {
loadMoreStatus.value = 'noMore'
} else {
loadMoreStatus.value = 'more'
}
} else {
uni.showToast({
title: res.msg || '加载失败',
icon: 'none'
})
}
} catch (error) {
uni.showToast({
title: '网络错误',
icon: 'none'
})
} finally {
loading.value = false
}
}
// 页面加载
onMounted(() => {
getData()
})
// 页面下拉刷新
const onPullDownRefresh = () => {
page.value = 1
loadMoreStatus.value = 'more'
getData().then(() => {
uni.stopPullDownRefresh()
})
}
// 导出页面生命周期方法
defineExpose({
onPullDownRefresh
})
</script>
<route type="page" lang="json">
{
"layout": "page",
"title": "直推报告",
"agent": true,
"auth": true
}
</route>

View File

@@ -98,10 +98,8 @@ function statusClass(state) {
</script>
<template>
<wd-notice-bar
text="为保证用户的隐私以及数据安全您的报告生成30天之后将自动清除请及时保存您的报告。" prefix="warn-bold" color="#007aff"
background-color="#f8f8f8"
/>
<!-- <wd-notice-bar text="为保证用户的隐私以及数据安全您的报告生成30天之后将自动清除请及时保存您的报告。" prefix="warn-bold" color="#007aff"
background-color="#f8f8f8" /> -->
<view class="flex flex-col gap-4 p-4">
<view v-for="item in reportList" :key="item.id" class="card flex flex-col gap-2" @click="toDetail(item)">
<view class="flex items-center justify-between">
@@ -117,7 +115,7 @@ function statusClass(state) {
报告类型
</view>
<view>
{{ getProductName(item.product_id) }}
{{ item.product_name }}
</view>
</view>
<view class="flex items-center justify-between">
@@ -148,9 +146,8 @@ function statusClass(state) {
}
</style>
<route lang="json">
{
"layout": "page",
"title": "历史报告"
}
</route>
<route lang="json">{
"layout": "page",
"title": "历史报告",
"auth": true
}</route>

View File

@@ -1,204 +0,0 @@
<script setup>
import CBad from '@/ui/CBad.vue'
import CBankLoanApplication from '@/ui/CBankLoanApplication.vue'
import CBankLoanBehavior from '@/ui/CBankLoanBehavior.vue'
import CLawsuit from '@/ui/CLawsuit.vue'
import CRelatedEnterprises from '@/ui/CRelatedEnterprises.vue'
import CSpecialList from '@/ui/CSpecialList.vue'
import CTabs from '@/ui/CTabs.vue'
import { queryResultByOrder } from '@/api/apis'
import CMarriage from '@/ui/CMarriage.vue'
const productMap = {
1: '背景调查',
2: '企业报告',
3: '家政服务',
4: '婚姻状态',
5: '贷前背景调查',
6: '租赁服务',
7: '个人风险评估',
}
// 根据 product_id 获取产品名称
function getProductName(productId) {
return productMap[productId] || '未知类型'
}
const productId = ref(null)
const isDone = ref(false)
const entData = ref(null)
const lawsuitData = ref(null)
const badData = ref(null)
const specialData = ref(null)
const bankLoanApplicationData = ref(null)
const marriageData = ref(null)
const bankLoanBehavior = ref(null)
const tabs = ref([
{ label: '报告概述', value: 'overview' },
])
const reportItems = ref([
])
const sortedReportItems = computed(() => {
return reportItems.value.slice().sort((a, b) => a.sort - b.sort)
})
const sortedTabs = computed(() => {
return tabs.value.slice().sort((a, b) => a.sort - b.sort)
})
onLoad((option) => {
console.log('option', option)
const { id } = option
if (id) {
queryResultByOrder(id).then((res) => {
console.log('res', res)
if (res.code === 200) {
productId.value = res.data.product_id
res.data.query_data.forEach((item) => {
if (item.success) {
switch (item.apiID) {
case 'G09SC02':
marriageData.value = item.data
tabs.value.push({ label: '婚姻状态', value: 'marriage', sort: 1 })
reportItems.value.push({ label: '婚姻状态', value: 'marriage', sort: 1 })
break
case 'G27BJ05':
bankLoanApplicationData.value = item.data
tabs.value.push({ label: '借贷申请记录', value: 'netloan', sort: 7 })
reportItems.value.push({ label: '借贷申请记录', value: 'netloan', sort: 7 })
break
case 'G28BJ05':
bankLoanBehavior.value = item.data
tabs.value.push({ label: '借贷记录', value: 'loan', sort: 6 })
reportItems.value.push({ label: '借贷记录', value: 'loan', sort: 6 })
break
case 'G26BJ05':
specialData.value = item.data
tabs.value.push({ label: '异常名单', value: 'special', sort: 5 })
reportItems.value.push({ label: '异常名单', value: 'special', sort: 5 })
break
case 'G05HZ01':
entData.value = item.data
tabs.value.push({ label: '关联企业', value: 'ent', sort: 4 })
reportItems.value.push({ label: '关联企业', value: 'ent', sort: 4 })
break
case 'G34BJ03':
badData.value = item.data
tabs.value.push({ label: '不良风险评估', value: 'bad', sort: 3 })
reportItems.value.push({ label: '不良风险评估', value: 'bad', sort: 3 })
break
case 'G35SC01':
lawsuitData.value = item.data
tabs.value.push({ label: '涉诉案件', value: 'lawsuit', sort: 2 })
reportItems.value.push({ label: '涉诉案件', value: 'lawsuit', sort: 2 })
break
default:
console.log(`未知的apiID: ${item.apiID}`)
}
}
})
}
}).finally(() => {
isDone.value = true
})
}
})
</script>
<template>
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
<CTabs
:tabs="sortedTabs"
type="blue-green"
/>
<template v-if="isDone">
<div class="flex flex-col gap-y-4 p-4 pt-12">
<div id="overview" class="title">
报告概述
</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<div class="flex justify-between">
<span class="text-gray-700 font-bold">报告时间</span>
<span class="text-gray-600">2024年11月18日 23:11:23</span>
</div>
<div class="flex justify-between">
<span class="text-gray-700 font-bold">报告项目</span>
<span class="text-gray-600">{{ getProductName(productId) }}</span>
</div>
</div>
<div>
<LTitle class="my-4" title="报告内容" type="blue-green" />
<div class="flex flex-col gap-y-2">
<div v-for="item in sortedReportItems" :key="item.value" class="flex justify-between">
<span class="text-gray-700 font-bold">{{ item.label }}</span>
<span class="text-green-500 font-bold">已解锁</span>
</div>
</div>
</div>
</div>
<template v-if="marriageData">
<div id="marriage" class="title">
婚姻状态
</div>
<CMarriage :data="marriageData" />
</template>
<template v-if="lawsuitData">
<div id="lawsuit" class="title">
涉诉案件
</div>
<CLawsuit :data="lawsuitData" />
</template>
<template v-if="badData">
<div id="bad" class="title">
不良风险评估
</div>
<CBad :data="badData" />
</template>
<template v-if="entData">
<div id="ent" class="title">
关联企业
</div>
<CRelatedEnterprises :data="entData" />
</template>
<template v-if="specialData">
<div id="special" class="title">
异常名单
</div>
<CSpecialList :data="specialData" />
</template>
<template v-if="bankLoanBehavior">
<div id="loan" class="title">
借贷记录
</div>
<CBankLoanBehavior :data="bankLoanBehavior" />
</template>
<template v-if="bankLoanApplicationData">
<div id="netloan" class="title">
贷款申请记录
</div>
<CBankLoanApplication :data="bankLoanApplicationData" />
</template>
<view class="card">
<view>
<view>
报告说明
</view>
<view>本报告的数据由用户本人明确授权后我们才向相关合法存有用户个人数据的机构调取本报告相关内容本平台只做大数据的获取与分析仅向用户个人展示参考</view><p> &nbsp; &nbsp; 报告有效期<strong>30</strong>过期自动删除 </p><p> &nbsp; &nbsp; 若您的数据不全面可能是数据具有延迟性或者合作信息机构未获取到您的数据若数据有错误请联系客服</p>
</view>
</view>
</div>
</template>
</div>
</template>
<style lang="scss" scoped>
</style>
<route lang="json">
{
"layout": "page",
"title": "报告结果"
}
</route>

View File

@@ -1,40 +0,0 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
const orderId = ref(null)
const token = ref(null)
const webviewSrc = ref('')
onLoad((option) => {
if (option.id) {
orderId.value = option.id
}
token.value = uni.getStorageSync('token') || ''
const baseUrl = 'https://app.quannengcha.com/report'
webviewSrc.value = `${baseUrl}?order_id=${encodeURIComponent(orderId.value)}&token=${encodeURIComponent(token.value)}`
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" :src="webviewSrc" />
</view>
</template>
<style lang="scss" scoped>
</style>
<route lang="json">
{
"layout": "page",
"title": "报告结果"
}
</route>

View File

@@ -0,0 +1,165 @@
<template>
<view class="min-h-screen bg-gray-50">
<!-- 收益列表 -->
<uni-list :loading="loading" :loadmore="loadMoreStatus" @loadmore="onLoadMore">
<!-- 空状态提示 -->
<view v-if="!loading && list.length === 0" class="flex flex-col items-center justify-center py-16">
<image src="/static/image/empty.svg" mode="aspectFit" class="w-48 h-48 mb-4" />
<text class="text-gray-400 text-base">暂无收益记录</text>
</view>
<view v-for="(item, index) in list" :key="index" class="mx-4 my-2 bg-white rounded-lg p-4 shadow-sm">
<view class="flex justify-between items-center mb-2">
<text class="text-gray-500 text-sm">{{ item.create_time || '-' }}</text>
<text class="text-green-500 font-bold">+{{ item.amount.toFixed(2) }}</text>
</view>
<view class="flex items-center">
<text class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium"
:class="getReportTypeStyle(item.type)">
<text class="w-2 h-2 rounded-full mr-1 inline-block" :class="getDotColor(item.type)"></text>
{{ typeToChinese(item.type) }}
</text>
</view>
</view>
<!-- 加载更多/加载完成提示 -->
<uni-load-more :status="loadMoreStatus" />
</uni-list>
</view>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { getAgentRewards } from '@/apis/agent'
// 类型映射配置
const typeConfig = {
descendant_promotion: {
chinese: '下级推广奖励',
color: { bg: 'bg-blue-100', text: 'text-blue-800', dot: 'bg-blue-500' }
},
descendant_upgrade_vip: {
chinese: '下级升级VIP奖励',
color: { bg: 'bg-green-100', text: 'text-green-800', dot: 'bg-green-500' }
},
descendant_upgrade_svip: {
chinese: '下级升级SVIP奖励',
color: { bg: 'bg-purple-100', text: 'text-purple-800', dot: 'bg-purple-500' }
},
descendant_stay_activedescendant: {
chinese: '下级活跃奖励',
color: { bg: 'bg-pink-100', text: 'text-pink-800', dot: 'bg-pink-500' }
},
new_active: {
chinese: '新增活跃奖励',
color: { bg: 'bg-orange-100', text: 'text-orange-800', dot: 'bg-orange-500' }
},
descendant_withdraw: {
chinese: '下级提现奖励',
color: { bg: 'bg-indigo-100', text: 'text-indigo-800', dot: 'bg-indigo-500' }
},
default: {
chinese: '其他奖励',
color: { bg: 'bg-gray-100', text: 'text-gray-800', dot: 'bg-gray-500' }
}
}
const page = ref(1)
const pageSize = ref(10)
const total = ref(0)
const list = ref([])
const loading = ref(false)
const loadMoreStatus = ref('more') // 'more'|'loading'|'noMore'
// 类型转中文
const typeToChinese = (type) => {
return typeConfig[type]?.chinese || typeConfig.default.chinese
}
// 获取颜色样式
const getReportTypeStyle = (type) => {
const config = typeConfig[type] || typeConfig.default
return `${config.color.bg} ${config.color.text}`
}
// 获取小圆点颜色
const getDotColor = (type) => {
return typeConfig[type]?.color.dot || typeConfig.default.color.dot
}
// 加载更多数据
const onLoadMore = async () => {
if (loadMoreStatus.value === 'noMore') return
page.value++
await getData()
}
// 获取数据
const getData = async () => {
try {
loading.value = true
loadMoreStatus.value = 'loading'
const res = await getAgentRewards({
page: page.value,
page_size: pageSize.value
})
if (res.code === 200) {
if (page.value === 1) {
list.value = res.data.list
total.value = res.data.total
} else {
list.value.push(...res.data.list)
}
if (list.value.length >= res.data.total || res.data.list.length < pageSize.value) {
loadMoreStatus.value = 'noMore'
} else {
loadMoreStatus.value = 'more'
}
} else {
uni.showToast({
title: res.msg || '加载失败',
icon: 'none'
})
}
} catch (error) {
uni.showToast({
title: '网络错误',
icon: 'none'
})
} finally {
loading.value = false
}
}
// 页面加载
onMounted(() => {
getData()
})
// 页面下拉刷新
const onPullDownRefresh = () => {
page.value = 1
loadMoreStatus.value = 'more'
getData().then(() => {
uni.stopPullDownRefresh()
})
}
// 导出页面生命周期方法
defineExpose({
onPullDownRefresh
})
</script>
<route type="page" lang="json">
{
"layout": "page",
"title": "收益明细",
"agent": true,
"auth": true
}
</route>

View File

@@ -1,22 +0,0 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" src="https://app.quannengcha.com/service" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "客户服务"
}
</route>

View File

@@ -1,22 +0,0 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" src="https://app.quannengcha.com/userAgreement" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "用户协议"
}
</route>

26
src/pages/vip.vue Normal file
View File

@@ -0,0 +1,26 @@
<template>
<view class="relative">
<image class="w-full" src="/static/images/vip_bg.png" mode="widthFix" />
<view @click="toService"
class="absolute left-[50%] translate-x-[-50%] bottom-80 bg-gradient-to-r from-gray-900 via-black to-gray-900 py-2 px-4 rounded-lg text-white text-[24px] font-bold shadow-[0_0_15px_rgba(255,255,255,0.3)]"
hover-class="scale-105">
点击马上报名
</view>
</view>
</template>
<script setup>
function toService() {
// 跳转到客服页面
uni.navigateTo({
url: 'https://work.weixin.qq.com/kfid/kfc5c19b2b93a5e73b9'
})
}
</script>
<style>
.scale-105 {
transform: scale(1.05);
transition: transform 0.3s;
}
</style>

427
src/pages/withdraw.vue Normal file
View File

@@ -0,0 +1,427 @@
<template>
<view class="min-h-screen bg-blue-50/30">
<view class="p-4">
<!-- 提现卡片 -->
<view class="bg-white rounded-lg p-5 mb-4">
<view class="flex items-center mb-6">
<view class="w-6 h-6 bg-orange-100 rounded-full flex items-center justify-center mr-2">
<text class="text-orange-400 text-sm"></text>
</view>
<text class="text-lg font-bold">支付宝提现</text>
</view>
<wd-form :model="form" :rules="rules" label-position="top" class="withdraw-form">
<!-- 支付宝账号 -->
<view class="mb-4">
<view class="mb-2">
<text class="text-red-500 mr-1">*</text>
<text class="text-base">支付宝账号</text>
</view>
<wd-input v-model="form.alipayAccount" prop="alipayAccount" placeholder="请输入支付宝账号"
custom-class="custom-input" />
<text class="text-gray-400 text-xs mt-1 block">可填写支付宝账户绑定的手机号</text>
</view>
<!-- 支付宝实名姓名 -->
<view class="mb-4">
<view class="mb-2">
<text class="text-red-500 mr-1">*</text>
<text class="text-base">实名姓名</text>
</view>
<wd-input v-model="form.realName" prop="realName" placeholder="请输入支付宝认证姓名" custom-class="custom-input" />
<text class="text-gray-400 text-xs mt-1 block">请填写支付宝账户认证的真实姓名</text>
</view>
<!-- 提现金额 -->
<view class="mb-4">
<view class="mb-2">
<text class="text-red-500 mr-1">*</text>
<text class="text-base">提现金额</text>
</view>
<view class="relative">
<wd-input v-model="form.amount" prop="amount" type="digit" placeholder="请输入提现金额"
custom-class="custom-input" @input="handleAmountInput" />
<view class="absolute right-2 top-1/2 transform -translate-y-1/2">
<view class="bg-blue-100 text-blue-600 rounded-full px-3 py-1 text-sm" @click="fillMaxAmount">
全部提现
</view>
</view>
</view>
</view>
</wd-form>
<!-- 金额提示 -->
<view class="text-sm text-gray-500 my-4">
可提现金额<text class="text-blue-600 font-semibold">¥{{ safeTruncate(availableAmount) }}</text>
</view>
<!-- 提现规则 -->
<view class="bg-gray-50 p-4 rounded-lg">
<view class="flex items-center">
<text class="text-orange-500 mr-1"></text>
<text class="text-blue-600 text-sm">提现须知</text>
</view>
<view class="text-xs text-gray-600 mt-2 space-y-1">
<text class="block">· 每日限提现1次最低50元</text>
<text class="block">· 超过800元需人工审核1-3个工作日</text>
<text class="block">· 到账时间24小时内</text>
</view>
</view>
</view>
<!-- 提交按钮 -->
<wd-button type="primary" block :loading="isSubmitting" @click="handleSubmit" custom-class="submit-button">
立即提现
</wd-button>
</view>
<!-- 状态弹窗 -->
<wd-popup v-model="popupVisible" custom-class="w-[85%] rounded-xl" closable close-on-click-modal>
<view class="p-8 bg-gradient-to-b from-white to-blue-50/30 relative">
<!-- 状态内容 -->
<view class="text-center space-y-5">
<!-- 状态图标 -->
<view class="relative inline-block">
<view class="w-14 h-14 rounded-full flex items-center justify-center" :class="statusIconClass[status]">
<text class="text-4xl">{{ statusIcon[status] }}</text>
</view>
</view>
<!-- 状态文案 -->
<view>
<text class="text-xl font-semibold mb-1 block" :class="statusTextColors[status]">
{{ statusMessages[status] }}
</text>
<template v-if="status === 2">
<text class="text-sm text-gray-500 block">
已向 <text class="text-blue-500">{{ form.alipayAccount }}</text> 转账
</text>
<text class="text-2xl font-bold text-green-600 mt-2 block">¥{{ form.amount }}</text>
</template>
<template v-if="status === 3">
<text class="text-red-500 text-sm px-4 block">{{ failMsg }}</text>
</template>
</view>
<!-- 进度条处理中状态 -->
<view v-if="status === 1" class="my-2">
<wd-progress :percentage="60" hide-text color="#4080ff" />
</view>
<!-- 辅助文案 -->
<view class="text-xs text-gray-400 space-y-1.5">
<template v-if="status === 2">
<text class="block">预计24小时内到账</text>
<text class="block">到账后可在支付宝账单中查看详情</text>
</template>
<template v-if="status === 1">
<text class="block">您的申请已进入处理队列</text>
<text class="block">5分钟后结果在提现记录中查看</text>
</template>
</view>
<!-- 操作按钮 -->
<wd-button type="primary" block class="mt-4" :style="{ backgroundColor: statusButtonColor[status] }"
@click="handlePopupAction">
{{ status === 1 ? '知道了' : status === 2 ? '完成' : '重新提现' }}
</wd-button>
</view>
</view>
</wd-popup>
<wd-toast />
</view>
</template>
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { useToast } from 'wot-design-uni'
import { getAgentRevenue, agentWithdrawal } from '@/apis/agent'
// 安全截断数字到指定小数位数(不进行四舍五入)
function safeTruncate(num, decimals = 2) {
if (isNaN(num) || !isFinite(num)) return "0.00";
const factor = 10 ** decimals;
const scaled = Math.trunc(num * factor);
const truncated = scaled / factor;
return truncated.toFixed(decimals);
}
// 表单数据
const form = ref({
alipayAccount: '',
realName: '',
amount: ''
})
const availableAmount = ref(0)
const isSubmitting = ref(false)
// 使用wot-design-ui的toast组件
const toast = useToast()
// 弹窗控制
const popupVisible = ref(false)
// 状态管理
const status = ref(null)
const failMsg = ref('')
// 表单验证规则
const rules = {
alipayAccount: [
{ required: true, message: '请输入支付宝账号' }
],
realName: [
{ required: true, message: '请输入姓名' },
{
required: true,
pattern: /^[\u4e00-\u9fa5]{2,4}$/,
message: '请输入2-4位中文姓名'
}
],
amount: [
{ required: true, message: '请输入提现金额' },
{
validator: (val) => {
const amountNum = Number(val)
if (isNaN(amountNum)) {
return '请输入有效金额'
}
// if (amountNum < 50) {
// return '提现金额不能低于50元'
// }
if (amountNum > availableAmount.value) {
return '超过可提现金额'
}
return true
}
}
]
}
// 样式配置
const statusIcon = {
1: '⏳',
2: '✅',
3: '❌'
}
const statusIconClass = {
1: 'bg-blue-100 text-blue-500 border-4 border-blue-200',
2: 'bg-green-100 text-green-500 border-4 border-green-200',
3: 'bg-red-100 text-red-500 border-4 border-red-200'
}
const statusTextColors = {
1: 'text-blue-600',
2: 'text-green-600',
3: 'text-red-600'
}
const statusButtonColor = {
1: '#3b82f6',
2: '#4ade80',
3: '#f87171'
}
const statusMessages = {
1: '提现申请处理中,请稍后再查询结果',
2: '提现成功',
3: '提现失败'
}
// 返回上一页
const handleBack = () => {
uni.navigateBack()
}
// 获取可提现金额
const getData = async () => {
try {
const res = await getAgentRevenue()
if (res.code === 200) {
availableAmount.value = res.data.balance
} else {
toast.error(res.msg || '获取余额失败')
}
} catch (error) {
toast.error('网络错误')
}
}
// 填充最大金额
const fillMaxAmount = () => {
// 使用safeTruncate确保金额正确截断到2位小数
form.value.amount = safeTruncate(availableAmount.value)
}
// 处理输入事件,控制输入格式
const handleAmountInput = (event) => {
let value = event.value
// 转为数字以便比较
let numValue = parseFloat(value)
// 如果超过可提现金额,设置为可提现金额并提示
if (!isNaN(numValue) && numValue > availableAmount.value) {
value = availableAmount.value
// 使用toast提示用户
toast.info(`金额已自动调整为最大可提现金额: ¥${value}`)
}
// 如果value的小数位数大于2位才进行截断处理
if (value.toString().includes('.') && value.toString().split('.')[1].length > 2) {
value = safeTruncate(value)
}
form.value.amount = value
console.log(value)
console.log(form.value.amount)
}
// 提交处理
const handleSubmit = async () => {
try {
// 提现金额转为数字
const amountNum = Number(form.value.amount)
// 验证表单
if (!form.value.alipayAccount.trim()) {
toast.info('请输入支付宝账号')
return
}
if (!form.value.realName.trim()) {
toast.info('请输入账户实名姓名')
return
}
if (!/^[\u4e00-\u9fa5]{2,4}$/.test(form.value.realName)) {
toast.info('请输入2-4位中文姓名')
return
}
if (!form.value.amount || isNaN(amountNum)) {
toast.info('请输入有效金额')
return
}
// if (amountNum < 50) {
// toast.info('提现金额不能低于50元')
// return
// }
if (amountNum > availableAmount.value) {
toast.info('超过可提现金额')
return
}
isSubmitting.value = true
const res = await agentWithdrawal({
payee_account: form.value.alipayAccount,
amount: amountNum,
payee_name: form.value.realName
})
if (res.code === 200) {
status.value = res.data.status
if (status.value === 3) {
failMsg.value = res.data.fail_msg
}
popupVisible.value = true
} else {
toast.error(res.msg || '提交失败')
}
} catch (error) {
toast.error('网络错误')
} finally {
isSubmitting.value = false
}
}
// 弹窗操作
const handlePopupAction = () => {
popupVisible.value = false
if (status.value === 2) {
resetForm()
getData()
}
}
// 重置表单
const resetForm = () => {
status.value = null
form.value = {
alipayAccount: '',
realName: '',
amount: ''
}
}
// 页面加载
onMounted(() => {
getData()
})
</script>
<style>
@keyframes progress {
0% {
width: 0;
}
100% {
width: 60%;
}
}
.animate-progress {
animation: progress 1.5s ease-in-out infinite;
animation-direction: alternate;
}
/* 自定义样式 */
.withdraw-form :deep(.wd-form-item) {
margin-bottom: 0;
}
.withdraw-form :deep(.wd-input__label) {
display: none;
}
.withdraw-form :deep(.custom-input .wd-input__inner) {
padding: 10px 15px;
font-size: 14px;
height: 45px;
border: none;
background-color: rgba(64, 128, 255, 0.05);
border-radius: 12px;
transition: all 0.3s ease;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.withdraw-form :deep(.custom-input:focus-within .wd-input__inner) {
border: 2px solid #4080ff;
background-color: rgba(64, 128, 255, 0.08);
box-shadow: 0 0 0 2px rgba(64, 128, 255, 0.1);
}
.withdraw-form :deep(.wd-input__prefix) {
display: none;
}
.submit-button {
height: 45px;
border-radius: 6px;
background-color: #4080ff !important;
font-size: 16px;
}
</style>
<route type="page" lang="json">{
"layout": "page",
"title": "提现",
"auth": true,
"agent": true
}</route>

View File

@@ -0,0 +1,181 @@
<template>
<view class="min-h-screen bg-gray-50">
<!-- 提现记录列表 -->
<uni-list :loading="loading" :loadmore="loadMoreStatus" @loadmore="onLoadMore">
<!-- 空状态提示 -->
<view v-if="!loading && list.length === 0" class="flex flex-col items-center justify-center py-16">
<image src="/static/image/empty.svg" mode="aspectFit" class="w-48 h-48 mb-4" />
<text class="text-gray-400 text-base">暂无提现记录</text>
</view>
<view v-for="(item, index) in list" :key="index" class="mx-4 my-2 bg-white rounded-lg p-4 shadow-sm">
<view class="flex justify-between items-center mb-2">
<text class="text-gray-500 text-sm">{{ item.create_time || '-' }}</text>
<text class="font-bold" :class="getAmountColor(item.status)">{{ item.amount.toFixed(2) }}</text>
</view>
<view class="flex items-center mb-2">
<text class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium"
:class="getStatusStyle(item.status)">
<text class="w-2 h-2 rounded-full mr-1 inline-block" :class="getDotColor(item.status)"></text>
{{ statusToChinese(item.status) }}
</text>
</view>
<view class="text-xs text-gray-500">
<text v-if="item.payee_account" class="block">收款账户{{ maskName(item.payee_account) }}</text>
<text v-if="item.remark" class="block">备注{{ item.remark }}</text>
</view>
</view>
<!-- 加载更多/加载完成提示 -->
<uni-load-more :status="loadMoreStatus" />
</uni-list>
</view>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { getWithdrawalRecords } from '@/apis/agent'
// 状态映射配置
const statusConfig = {
1: {
chinese: '处理中',
color: {
bg: 'bg-yellow-100',
text: 'text-yellow-800',
dot: 'bg-yellow-500',
amount: 'text-yellow-500'
}
},
2: {
chinese: '提现成功',
color: {
bg: 'bg-green-100',
text: 'text-green-800',
dot: 'bg-green-500',
amount: 'text-green-500'
}
},
3: {
chinese: '提现失败',
color: {
bg: 'bg-red-100',
text: 'text-red-800',
dot: 'bg-red-500',
amount: 'text-red-500'
}
}
}
const page = ref(1)
const pageSize = ref(10)
const total = ref(0)
const list = ref([])
const loading = ref(false)
const loadMoreStatus = ref('more') // 'more'|'loading'|'noMore'
// 账户脱敏处理
const maskName = (name) => {
if (!name || typeof name !== 'string') return ''
if (name.length <= 7) return name
return name.substring(0, 3) + '****' + name.substring(7)
}
// 状态转中文
const statusToChinese = (status) => {
return statusConfig[status]?.chinese || '未知状态'
}
// 获取状态样式
const getStatusStyle = (status) => {
const config = statusConfig[status] || {}
return `${config.color?.bg || 'bg-gray-100'} ${config.color?.text || 'text-gray-800'}`
}
// 获取小圆点颜色
const getDotColor = (status) => {
return statusConfig[status]?.color.dot || 'bg-gray-500'
}
// 获取金额颜色
const getAmountColor = (status) => {
return statusConfig[status]?.color.amount || 'text-gray-500'
}
// 加载更多数据
const onLoadMore = async () => {
if (loadMoreStatus.value === 'noMore') return
page.value++
await getData()
}
// 获取数据
const getData = async () => {
try {
loading.value = true
loadMoreStatus.value = 'loading'
const res = await getWithdrawalRecords({
page: page.value,
page_size: pageSize.value
})
if (res.code === 200) {
if (page.value === 1) {
list.value = res.data.list
total.value = res.data.total
} else {
list.value.push(...res.data.list)
}
if (list.value.length >= res.data.total || res.data.list.length < pageSize.value) {
loadMoreStatus.value = 'noMore'
} else {
loadMoreStatus.value = 'more'
}
} else {
uni.showToast({
title: res.msg || '加载失败',
icon: 'none'
})
}
} catch (error) {
uni.showToast({
title: '网络错误',
icon: 'none'
})
} finally {
loading.value = false
}
}
// 页面加载
onMounted(() => {
getData()
})
// 页面下拉刷新
const onPullDownRefresh = () => {
page.value = 1
loadMoreStatus.value = 'more'
getData().then(() => {
uni.stopPullDownRefresh()
})
}
// 导出页面生命周期方法
defineExpose({
onPullDownRefresh
})
</script>
<style>
/* 自定义样式 */
</style>
<route type="page" lang="json">{
"layout": "page",
"title": "提现记录",
"auth": true,
"agent": true
}</route>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Some files were not shown because too many files have changed in this diff Show More