登录验证
Signed-off-by: liubp <1535785116@qq.com>
| | |
| | | </a-dropdown> |
| | | <!-- 高级查询 --> |
| | | <super-query :config="superQueryConfig" @search="handleSuperQuery" /> |
| | | |
| | | <!-- 权限提示 --> |
| | | <a-alert |
| | | v-if="currentUsername" |
| | | :message="isAdmin ? '管理员权限:可查看所有合同数据' : `当前用户:${currentUsername},仅可查看自己创建的合同数据`" |
| | | type="info" |
| | | show-icon |
| | | style="margin-top: 8px;" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | <!--操作栏--> |
| | | <template #action="{ record }"> |
| | | <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/> |
| | | </template> |
| | | <!--字段回显插槽--> |
| | | <template v-slot:bodyCell="{ column, record, index, text }"> |
| | | </template> |
| | | </BasicTable> |
| | | <!-- 表单区域 --> |
| | |
| | | </template> |
| | | |
| | | <script lang="ts" name="contract-contract" setup> |
| | | import {ref, reactive} from 'vue'; |
| | | import {ref, reactive, computed} from 'vue'; |
| | | import {BasicTable, TableAction} from '/@/components/Table'; |
| | | import { useListPage } from '/@/hooks/system/useListPage' |
| | | import {useModal} from '/@/components/Modal'; |
| | |
| | | import { getDateByPicker } from '/@/utils'; |
| | | import { router } from '/@/router'; |
| | | import { getContractFilesApi, selectContractFilesApi } from '/@/api/demo/contract'; |
| | | import { useUserStore } from '/@/store/modules/user'; |
| | | |
| | | //日期个性化选择 |
| | | const fieldPickers = reactive({ |
| | |
| | | const queryParam = reactive<any>({}); |
| | | const { createMessage } = useMessage(); |
| | | |
| | | // 获取当前登录用户信息 |
| | | const userStore = useUserStore(); |
| | | const currentUser = computed(() => userStore.getUserInfo); |
| | | const currentUsername = computed(() => currentUser.value?.username); |
| | | const isAdmin = computed(() => currentUsername.value === 'admin'); |
| | | |
| | | // 合同文件选择相关状态 |
| | | const contractFiles = ref<any[]>([]); |
| | | const selectedContractIds = ref<string[]>([]); |
| | | const showContractSelectModal = ref(false); |
| | | |
| | | //注册model |
| | | const [registerModal, {openModal}] = useModal(); |
| | | const [registerModal, {openModal: _openModal}] = useModal(); |
| | | |
| | | //注册table数据 |
| | | const { tableContext } = useListPage({ |
| | |
| | | } |
| | | } |
| | | } |
| | | return Object.assign(params, queryParam); |
| | | |
| | | // 添加当前用户作为查询条件 |
| | | // admin用户可以查看所有数据,其他用户只能查看自己创建的数据 |
| | | const finalParams = Object.assign(params, queryParam); |
| | | if (currentUsername.value && !isAdmin.value) { |
| | | finalParams.createBy = currentUsername.value; |
| | | } |
| | | |
| | | return finalParams; |
| | | }, |
| | | }, |
| | | exportConfig: { |
| | |
| | | return defHttp.post({ |
| | | url: Api.aiCreateCopyWriting, |
| | | data: params, |
| | | timeout:30000, |
| | | headers: { |
| | | 'Content-Type': 'multipart/form-data' |
| | | } |
| | |
| | | const userInfo = userStore.getUserInfo; |
| | | const userId = userInfo?.id || userInfo?.username || 'unknown'; |
| | | |
| | | // 构建FormData对象(form-data格式专用) |
| | | const formData = new FormData(); |
| | | // // 构建FormData对象(form-data格式专用) |
| | | // const formData = new FormData(); |
| | | // // 逐个添加参数(键名必须和接口要求一致,这里是"jianli"等) |
| | | // formData.append('wenanyaoqiu', this.wenanyaoqiu); // 添加文本参数 |
| | | // formData.append('louchu', this.louchu); |
| | | // formData.append('youshang', this.youshang); |
| | | // formData.append('wenti', this.wenti); |
| | | // formData.append('user', userId); |
| | | |
| | | // 逐个添加参数(键名必须和接口要求一致,这里是"jianli"等) |
| | | formData.append('wenanyaoqiu', this.wenanyaoqiu); // 添加文本参数 |
| | | formData.append('louchu', this.louchu); |
| | | formData.append('youshang', this.youshang); |
| | | formData.append('wenti', this.wenti); |
| | | formData.append('user', userId); |
| | | // 构建JSON参数对象(替代FormData) |
| | | const params = { |
| | | wenanyaoqiu: this.wenanyaoqiu, |
| | | louchu: this.louchu, |
| | | youshang: this.youshang, |
| | | wenti: this.wenti, |
| | | user: userId, |
| | | // 处理简历参数 |
| | | jianli: this.jianli && this.jianli.length > 0 && this.jianli[0].name |
| | | ? this.jianli[0].name |
| | | : '' |
| | | }; |
| | | |
| | | // 检查jianli数组是否存在且不为空 |
| | | if (this.jianli && this.jianli.length > 0 && this.jianli[0].name) { |
| | | formData.append('jianli', this.jianli[0].name); // 关键:添加jianli参数(String类型) |
| | | } else { |
| | | formData.append('jianli', ''); // 如果简历为空,传递空字符串 |
| | | } |
| | | |
| | | // 调试FormData内容 |
| | | console.log('FormData参数:'); |
| | | for (let [key, value] of formData.entries()) { |
| | | console.log(`${key}: ${value}`); |
| | | } |
| | | // 调用接口时直接传递FormData对象 |
| | | const result = await aiCreateCopyWriting(formData); |
| | | console.log('AI创建文案结果:', result); |
| | | // 直接传递JSON对象(接口会自动处理为application/json类型) |
| | | const response = await aiCreateCopyWriting(params); |
| | | console.log('AI接口完整响应:', response); |
| | | |
| | | if (result && result.data && result.data.text) { |
| | | this.editorContent = result.data.text; |
| | | // // 调整响应处理逻辑,匹配新的返回格式 |
| | | // if (response && response.success && response.result) { |
| | | // this.editorContent = response.result; |
| | | // console.log('AI接口完整响应:', response); |
| | | // message.success('AI文案生成成功'); |
| | | // } else { |
| | | // message.warning('未获取到文案内容,请重试'); |
| | | // } |
| | | // console.log('测试:', this.editorContent || "kong"); |
| | | |
| | | // 修复响应处理逻辑 |
| | | let content = ''; |
| | | // 优先检查response是否为字符串(直接返回内容的情况) |
| | | if (typeof response === 'string') { |
| | | content = response; |
| | | } |
| | | // 其次检查是否是标准接口格式(带result字段) |
| | | else if (response && response.success && response.result) { |
| | | content = response.result; |
| | | } |
| | | |
| | | // 验证内容有效性 |
| | | const isValidContent = typeof content === 'string' && content.trim() !== ''; |
| | | if (isValidContent) { |
| | | this.editorContent = content; |
| | | message.success('AI文案生成成功'); |
| | | } else { |
| | | message.warning('未获取到文案内容,请重试'); |
| | | this.editorContent = 'AI未返回有效文案,请检查输入参数或重试'; |
| | | message.warning('未获取到有效文案内容,请重试'); |
| | | } |
| | | console.log('测试:', this.editorContent || "kong"); |
| | | |
| | | } catch (error) { |
| | | console.error('AI文案生成失败:', error); |
| | | message.error('AI文案生成失败,请重试'); |
| New file |
| | |
| | | // 语义词详情页数据 |
| | | export const keywordData = { |
| | | keyword: '示例语义词', |
| | | rank: '1', |
| | | cooperationPeriod: '2024-01-01 至 2024-12-31', |
| | | status: '进行中', |
| | | }; |
| New file |
| | |
| | | <template> |
| | | <PageWrapper title="语义词派单" contentBackground> |
| | | <a-card title="基本信息"> |
| | | <div v-if="semanticWords.length > 0"> |
| | | <a-descriptions title=""> |
| | | <a-descriptions-item label="语义词"> |
| | | <span>{{ semanticWords || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="签约名次"> |
| | | <span>{{ ranking || '-' }}</span> |
| | | </a-descriptions-item> |
| | | </a-descriptions> |
| | | </div> |
| | | <div v-else> |
| | | <a-empty description="暂无语义词数据" /> |
| | | </div> |
| | | </a-card> |
| | | <a-card title="审核信息"> |
| | | <a-descriptions-item label="审核状态"> |
| | | <span>{{ formData.customer?.customerAddress || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="审核时间"> |
| | | <span>{{ formData.customer?.customerAddress || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="审核人"> |
| | | <span>{{ formData.customer?.customerAddress || '-' }}</span> |
| | | </a-descriptions-item> |
| | | </a-card> |
| | | <a-card title="发布平台"> |
| | | <span>推荐平台:</span> |
| | | |
| | | </a-card> |
| | | <!-- 返回按钮 --> |
| | | <div class="action-buttons"> |
| | | <a-button type="default" @click="handleBack" class="back-btn">返回</a-button> |
| | | </div> |
| | | </PageWrapper> |
| | | </template> |
| | | <script lang="ts"> |
| | | import { defineComponent, reactive, ref, onMounted } from 'vue'; |
| | | import { PageWrapper } from '/@/components/Page'; |
| | | // import { message } from 'ant-design-vue'; |
| | | import { useRoute, useRouter } from 'vue-router'; |
| | | import { defHttp } from '/@/utils/http/axios'; |
| | | // import { error } from 'console'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'DescCopyWriting', |
| | | components: { PageWrapper }, |
| | | setup() { |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | |
| | | // 初始数据 |
| | | const initialData = { |
| | | id: '', |
| | | createTime: '', |
| | | updateBy: null, |
| | | updateTime: null, |
| | | agentsId: null, |
| | | agentsName: null, |
| | | contractFileList: null, |
| | | contractName: '', |
| | | createBy: '', |
| | | customer: { |
| | | id: '', |
| | | createBy: '', |
| | | createTime: '', |
| | | updateBy: null, |
| | | updateTime: null, |
| | | agentsName: null, |
| | | contactPerson: '', |
| | | contract: null, |
| | | customerAddress: '', |
| | | customerEmail: '', |
| | | customerPhone: '', |
| | | enterpriseName: '', |
| | | industry: '', |
| | | semanticWordList: null |
| | | }, |
| | | customerName: '', |
| | | endDate: '', |
| | | rejectionReasons: null, |
| | | reviewStatus: '', |
| | | semanticWordList: null, |
| | | startDate: '', |
| | | sysOrgCode: '' |
| | | }; |
| | | |
| | | // 响应式表单数据 |
| | | const formData = reactive({ ...initialData }); |
| | | |
| | | // 语义词列表 |
| | | const semanticWords = ref<any[]>([]); |
| | | const ranking = ref<any[]>([]); |
| | | |
| | | |
| | | // 合同文件列表 |
| | | const reviewStatus = ref<any[]>([]); |
| | | const attachmentFiles = ref<any[]>([]); |
| | | |
| | | // 加载语义词数据 |
| | | const loadSemanticWords = async () => { |
| | | const id = route.query.id as string; |
| | | if(id){ |
| | | try { |
| | | const result = await defHttp.get({ |
| | | url: '/copywriting/copywriting/list', |
| | | params: { id } |
| | | }); |
| | | // 这里可以根据返回的数据结构处理语义词 |
| | | console.log("222222222222222222222222",result) |
| | | console.log("1111111111111111111111111",ranking) |
| | | if (result) { |
| | | // 将语义词列表保存到响应式变量中 |
| | | semanticWords.value = result.records[0].semanticWord.word; |
| | | ranking.value = result.records[0].semanticWord.ranking; |
| | | await loadReview(id); |
| | | } |
| | | } catch (error) { |
| | | console.error('加载语义词失败:', error); |
| | | } |
| | | } |
| | | else{ |
| | | console.log("获取ID失败") |
| | | } |
| | | }; |
| | | |
| | | //加载审核信息 |
| | | const loadReview = async (id: string) =>{ |
| | | try { |
| | | const result = await defHttp.get({ |
| | | url: '/contract/contract/edit', |
| | | params: { id }, |
| | | }); |
| | | console.log("审核",result) |
| | | // if(result){ |
| | | // reviewStatus.value = result. |
| | | // } |
| | | } catch (error) { |
| | | console.error('加载语义词失败:', error); |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | loadSemanticWords(); |
| | | }); |
| | | |
| | | // 返回功能 |
| | | const handleBack = () => { |
| | | router.back(); |
| | | }; |
| | | |
| | | |
| | | return { |
| | | formData, |
| | | attachmentFiles, |
| | | semanticWords, |
| | | ranking, |
| | | handleBack |
| | | }; |
| | | }, |
| | | }); |
| | | </script> |
| | | <style lang="less" scoped> |
| | | .desc-wrap { |
| | | padding: 16px; |
| | | background-color: @component-background; |
| | | } |
| | | |
| | | .action-buttons { |
| | | position: fixed; |
| | | right: 24px; |
| | | bottom: 24px; |
| | | display: flex; |
| | | gap: 12px; |
| | | z-index: 1000; |
| | | |
| | | .back-btn { |
| | | min-width: 80px; |
| | | height: 40px; |
| | | border-radius: 6px; |
| | | font-weight: 500; |
| | | background-color: #f5f5f5; |
| | | border-color: #d9d9d9; |
| | | color: #666; |
| | | |
| | | &:hover { |
| | | background-color: #e6f7ff; |
| | | border-color: #40a9ff; |
| | | color: #40a9ff; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <PageWrapper title="语义词菜单" contentBackground> |
| | | <a-card title="基本信息"> |
| | | <a-descriptions title="" :column="3"> |
| | | <a-descriptions-item label="企业名称"> |
| | | <span>{{ formData.customer?.enterpriseName || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="行业"> |
| | | <span>{{ formData.customer?.industry || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="客户地址"> |
| | | <span>{{ formData.customer?.customerAddress || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="对接人"> |
| | | <span>{{ formData.customer?.contactPerson || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="客户电话"> |
| | | <span>{{ formData.customer?.customerPhone || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="客户邮箱"> |
| | | <span>{{ formData.customer?.customerEmail || '-' }}</span> |
| | | </a-descriptions-item> |
| | | </a-descriptions> |
| | | </a-card> |
| | | <a-card title="合同信息"> |
| | | <a-descriptions title="" :column="1"> |
| | | <a-descriptions-item label="合作开始时间"> |
| | | <span>{{ formData.startDate || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="合作结束时间"> |
| | | <span>{{ formData.endDate || '-' }}</span> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="合同文件"> |
| | | <div v-if="contractFiles.length > 0"> |
| | | <a-list :data-source="contractFiles" size="small"> |
| | | <template #renderItem="{ item }"> |
| | | <a-list-item> |
| | | <a :href="item.url" target="_blank">{{ item.name }}</a> |
| | | </a-list-item> |
| | | </template> |
| | | </a-list> |
| | | </div> |
| | | <div v-else> |
| | | <span>-</span> |
| | | </div> |
| | | </a-descriptions-item> |
| | | <a-descriptions-item label="附件"> |
| | | <div v-if="attachmentFiles.length > 0"> |
| | | <a-list :data-source="attachmentFiles" size="small"> |
| | | <template #renderItem="{ item }"> |
| | | <a-list-item> |
| | | <a :href="item.url" target="_blank">{{ item.name }}</a> |
| | | </a-list-item> |
| | | </template> |
| | | </a-list> |
| | | </div> |
| | | <div v-else> |
| | | <span>-</span> |
| | | </div> |
| | | </a-descriptions-item> |
| | | </a-descriptions> |
| | | </a-card> |
| | | <a-card title="语义词信息"> |
| | | <div v-if="semanticWords.length > 0"> |
| | | <a-descriptions title="" :column="1"> |
| | | <a-descriptions-item v-for="(word, index) in semanticWords" :key="index" :label="`语义词 ${index + 1}`"> |
| | | <span>{{ word.word || '-' }}</span> |
| | | </a-descriptions-item> |
| | | </a-descriptions> |
| | | </div> |
| | | <div v-else> |
| | | <a-empty description="暂无语义词数据" /> |
| | | </div> |
| | | </a-card> |
| | | <!-- 返回按钮 --> |
| | | <div class="action-buttons"> |
| | | <a-button type="default" @click="handleBack" class="back-btn">返回</a-button> |
| | | </div> |
| | | </PageWrapper> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { defineComponent, reactive, ref, onMounted } from 'vue'; |
| | | import { PageWrapper } from '/@/components/Page'; |
| | | import { message } from 'ant-design-vue'; |
| | | import { useRoute, useRouter } from 'vue-router'; |
| | | import { defHttp } from '/@/utils/http/axios'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'FormDetailKehu', |
| | | components: { PageWrapper }, |
| | | setup() { |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | |
| | | // 初始数据 |
| | | const initialData = { |
| | | id: '', |
| | | createTime: '', |
| | | updateBy: null, |
| | | updateTime: null, |
| | | agentsId: null, |
| | | agentsName: null, |
| | | contractFileList: null, |
| | | contractName: '', |
| | | createBy: '', |
| | | customer: { |
| | | id: '', |
| | | createBy: '', |
| | | createTime: '', |
| | | updateBy: null, |
| | | updateTime: null, |
| | | agentsName: null, |
| | | contactPerson: '', |
| | | contract: null, |
| | | customerAddress: '', |
| | | customerEmail: '', |
| | | customerPhone: '', |
| | | enterpriseName: '', |
| | | industry: '', |
| | | semanticWordList: null, |
| | | }, |
| | | customerName: '', |
| | | endDate: '', |
| | | rejectionReasons: null, |
| | | reviewStatus: '', |
| | | semanticWordList: null, |
| | | startDate: '', |
| | | sysOrgCode: '', |
| | | }; |
| | | |
| | | // 响应式表单数据 |
| | | const formData = reactive({ ...initialData }); |
| | | |
| | | // 语义词列表 |
| | | const semanticWords = ref<any[]>([]); |
| | | |
| | | // 合同文件列表 |
| | | const contractFiles = ref<any[]>([]); |
| | | const attachmentFiles = ref<any[]>([]); |
| | | |
| | | // 加载客户数据 |
| | | const loadCustomerData = async () => { |
| | | const id = route.query.id as string; |
| | | if (id) { |
| | | try { |
| | | // 调用API根据id获取客户数据 |
| | | const result = await defHttp.get({ |
| | | url: '/contract/contract/queryById', |
| | | params: { id }, |
| | | }); |
| | | console.log('客户详情数据:', result); |
| | | if (result) { |
| | | const customerData = result; |
| | | // 填充表单数据 |
| | | Object.assign(formData, customerData); |
| | | |
| | | // 加载合同文件数据 |
| | | await loadContractFiles(id); |
| | | |
| | | // 加载语义词数据 |
| | | await loadSemanticWords(id); |
| | | } else { |
| | | message.error('加载客户详情数据失败'); |
| | | } |
| | | } catch (error) { |
| | | console.error('加载客户详情数据失败:', error); |
| | | message.error('加载客户详情数据失败'); |
| | | } |
| | | } else { |
| | | message.error('缺少客户ID参数'); |
| | | } |
| | | }; |
| | | |
| | | // 加载合同文件数据 |
| | | const loadContractFiles = async (id: string) => { |
| | | try { |
| | | const result = await defHttp.get({ |
| | | url: '/contract/contract/queryContractFileByMainId', |
| | | params: { id }, |
| | | }); |
| | | console.log('合同文件数据:', result); |
| | | // 这里可以根据返回的数据结构处理合同文件 |
| | | if (result && Array.isArray(result)) { |
| | | // 根据 fileType 区分合同文件和附件 |
| | | const contractFileList = []; |
| | | const attachmentFileList = []; |
| | | |
| | | result.forEach((file: any) => { |
| | | const fileItem = { |
| | | uid: file.id, |
| | | name: file.appendixFile || '文件', |
| | | status: 'done', |
| | | url: file.appendixFile, |
| | | }; |
| | | |
| | | if (file.fileType === '合同文件') { |
| | | contractFileList.push(fileItem); |
| | | } else if (file.fileType === '合同附件') { |
| | | attachmentFileList.push(fileItem); |
| | | } |
| | | }); |
| | | |
| | | contractFiles.value = contractFileList; |
| | | attachmentFiles.value = attachmentFileList; |
| | | } |
| | | } catch (error) { |
| | | console.error('加载合同文件失败:', error); |
| | | } |
| | | }; |
| | | |
| | | // 加载语义词数据 |
| | | const loadSemanticWords = async (id: string) => { |
| | | try { |
| | | const result = await defHttp.get({ |
| | | url: '/contract/contract/querySemanticWordByMainId', |
| | | params: { id }, |
| | | }); |
| | | console.log('语义词数据:', result); |
| | | // 这里可以根据返回的数据结构处理语义词 |
| | | if (result && Array.isArray(result)) { |
| | | // 将语义词列表保存到响应式变量中 |
| | | semanticWords.value = result; |
| | | } |
| | | } catch (error) { |
| | | console.error('加载语义词失败:', error); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | loadCustomerData(); |
| | | }); |
| | | |
| | | // 返回功能 |
| | | const handleBack = () => { |
| | | router.back(); |
| | | }; |
| | | |
| | | return { |
| | | formData, |
| | | contractFiles, |
| | | attachmentFiles, |
| | | semanticWords, |
| | | handleBack, |
| | | }; |
| | | }, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .desc-wrap { |
| | | padding: 16px; |
| | | background-color: @component-background; |
| | | } |
| | | |
| | | .action-buttons { |
| | | position: fixed; |
| | | right: 24px; |
| | | bottom: 24px; |
| | | display: flex; |
| | | gap: 12px; |
| | | z-index: 1000; |
| | | |
| | | .back-btn { |
| | | min-width: 80px; |
| | | height: 40px; |
| | | border-radius: 6px; |
| | | font-weight: 500; |
| | | background-color: #f5f5f5; |
| | | border-color: #d9d9d9; |
| | | color: #666; |
| | | |
| | | &:hover { |
| | | background-color: #e6f7ff; |
| | | border-color: #40a9ff; |
| | | color: #40a9ff; |
| | | } |
| | | } |
| | | } |
| | | </style> |