zs 3 months ago
parent
commit
43562dbaf4

+ 1 - 1
src/components/custom/custom-upload.vue

@@ -1,6 +1,6 @@
 <template>
   <div id="c-upload">
-    <el-upload v-if="url" ref="upload" :action="url" :limit="limit" :accept="accept" :file-list="list" :list-type="listType" :on-exceed="outLimit" :on-preview="filePreview" :on-success="onSuccess" :before-remove="onRemove">
+    <el-upload v-if="url" ref="upload" :action="url" :limit="limit" :accept="accept" :file-list="list" :list-type="listType" :on-exceed="outLimit" :on-preview="filePreview" :on-success="onSuccess" :on-remove="onRemove">
       <el-button type="primary">选择文件</el-button>
       <template #tip v-if="tip">
         <p style="color: #ff0000">{{ tip }}</p>

+ 7 - 1
src/components/index.js

@@ -1,7 +1,13 @@
 export default function globalComponents(app) {
   const components = import.meta.glob('./**/**.{vue,tsx}', { eager: true }) //获取文件夹及其嵌套的多级子文件夹
   for (let [key, value] of Object.entries(components)) {
-    const name = key.replace('./', '').split('/')[0]
+    let name = key.replace('./', '').split('/')[0]
+    if (name == 'custom') {
+      name = key
+        .replace('./custom/', '')
+        .split('/')[0]
+        .replace(/\.vue$/, '')
+    }
     app.component(value.default.name || name, value.default)
   }
 }

+ 1 - 1
src/layout/index.vue

@@ -102,7 +102,7 @@ const toOut = () => {
 }
 // 返回首页
 const toHome = () => {
-  router.push({ path: `/` })
+  router.push({ path: `/one` })
 }
 watch(
   route,

+ 6 - 0
src/store/api/platform/matchExt.js

@@ -30,11 +30,17 @@ export const MatchExtStore = defineStore('matchExt', () => {
     const res = await axios.$delete(`${url}/${payload}`)
     return res
   }
+  const firstStep = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/firstStep/${id}`, payload)
+    return res
+  }
   return {
     query,
     fetch,
     create,
     update,
+    firstStep,
     del
   }
 })

+ 262 - 168
src/views/center/match.vue

@@ -30,13 +30,14 @@
             </el-table-column>
             <el-table-column align="center" label="操作" width="250">
               <template #default="{ row }">
-                <el-link v-if="row.form == '4'" :underline="false" type="primary" size="mini" @click="toPreliminary(row)" style="margin-right: 10px">查看初赛信息</el-link>
-                <el-link v-if="row.status == '-2'" :underline="false" type="warning" size="mini" @click="toExam(row)" style="margin-right: 10px">提交审核</el-link>
-                <el-link v-if="row.match_status == '2' && row.form != '3'" :underline="false" type="primary" size="mini" @click="toScore(row)" style="margin-right: 10px">分数</el-link>
-                <el-link :underline="false" type="warning" size="mini" @click="toSign(row)" style="margin-right: 10px">报名</el-link>
-                <el-link :underline="false" type="primary" size="mini" @click="toEdit(row)" style="margin-right: 10px">修改</el-link>
-                <el-link v-if="row.status != '1'" :underline="false" type="danger" size="mini" style="margin-right: 10px" @click="toDelete(row)"> 删除 </el-link>
-                <el-link :underline="false" type="primary" size="mini" @click="toMatch(row)">赛事状态修改</el-link>
+                <el-link v-if="row.form == '4'" :underline="false" type="primary" @click="toPreliminary(row)" style="margin-right: 10px">初赛报名名单</el-link>
+                <el-link v-if="row.status == '-2'" :underline="false" type="warning" @click="toExam(row)" style="margin-right: 10px">提交审核</el-link>
+                <el-link v-if="row.match_status == '2' && row.form != '4' && row.form != '3'" :underline="false" type="primary" @click="toScore(row)" style="margin-right: 10px"> 分数 </el-link>
+                <el-link v-if="row.form != '4'" :underline="false" type="warning" @click="toSign(row)" style="margin-right: 10px">报名</el-link>
+                <el-link :underline="false" type="primary" @click="toEdit(row)" style="margin-right: 10px">修改</el-link>
+                <el-link v-if="row.status != '1'" :underline="false" type="danger" style="margin-right: 10px" @click="toDelete(row)"> 删除 </el-link>
+                <el-link :underline="false" type="primary" @click="toMatch(row)" style="margin-right: 10px">赛事状态修改</el-link>
+                <el-link v-if="row.form == '4'" :underline="false" type="primary" @click="toExtOne(row)">赛事设置</el-link>
               </template>
             </el-table-column>
           </el-table>
@@ -49,46 +50,79 @@
     <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose">
       <el-row>
         <el-col :span="24" v-if="dialog.type == '1'">
-          <el-tabs v-model="activeName" type="card">
-            <el-tab-pane label="基本信息" name="first">
-              <custom-form v-model="form" :fields="oneformFields" :rules="rules" @save="toSave" @draftSave="toDraftSave">
-                <template #video>
-                  <custom-upload model="video" :list="form.video" :limit="1" url="/files/web/cxyy_match/upload" @change="onUpload"></custom-upload>
-                </template>
-                <template #file>
+          <el-form ref="formRef" :model="form" :rules="rules" label-width="auto">
+            <el-tabs v-model="activeName" type="card">
+              <el-tab-pane label="基本信息" name="first">
+                <el-form-item label="封面" prop="file">
                   <custom-upload model="file" :list="form.file" :limit="1" listType="picture-card" url="/files/web/cxyy_match/upload" @change="onUpload"></custom-upload>
-                </template>
-                <template #is_use>
-                  <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-                </template>
-                <template #is_show>
-                  <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-                </template>
-                <template #industry>
-                  <el-option v-for="i in industryList" :key="i.id" :label="i.label" :value="i.value"></el-option>
-                </template>
-                <template #scale>
-                  <el-radio v-for="i in scaleList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-                </template>
-                <template #match_type>
-                  <el-radio v-for="i in matchTypeList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-                </template>
-                <template #type>
-                  <el-option v-for="i in typeList" :key="i.id" :label="i.label" :value="i.value"></el-option>
-                </template>
-                <template #form>
-                  <el-option v-for="i in formList" :key="i.id" :label="i.label" :value="i.value"></el-option>
-                </template>
-                <template #tags>
-                  <el-select v-model="form.tags" multiple filterable allow-create default-first-option :reserve-keyword="false" placeholder="请选择标签" style="width: 100%">
+                </el-form-item>
+                <el-form-item label="赛事名称" prop="name">
+                  <el-input size="large" v-model="form.name" placeholder="请输入赛事名称" />
+                </el-form-item>
+                <el-form-item label="类别" prop="form">
+                  <el-select v-model="form.form" placeholder="请选择类别" size="large" style="width: 100%">
+                    <el-option v-for="item in formList" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="标签" prop="tags">
+                  <el-select size="large" v-model="form.tags" multiple filterable allow-create default-first-option :reserve-keyword="false" placeholder="请选择标签" style="width: 100%">
                     <el-option v-for="item in tagsList" :key="item.id" :label="item.title" :value="item.title" />
                   </el-select>
-                </template>
-              </custom-form>
-            </el-tab-pane>
-            <el-tab-pane label="拓展信息" name="second">
-              <custom-form v-model="form" :fields="twoformFields" :rules="{}" @save="toSave" @draftSave="toDraftSave">
-                <template #rules>
+                </el-form-item>
+                <el-form-item label="类型" prop="type">
+                  <el-select v-model="form.type" placeholder="请选择类型" size="large" style="width: 100%">
+                    <el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="赛事规模" prop="scale">
+                  <el-radio-group v-model="form.scale">
+                    <el-radio v-for="item in scaleList" :key="item.value" :value="item.value" size="large">{{ item.label }}</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+                <el-form-item label="赛事类型" prop="match_type">
+                  <el-radio-group v-model="form.match_type">
+                    <el-radio v-for="item in matchTypeList" :key="item.value" :value="item.value" size="large">{{ item.label }}</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+                <el-form-item label="路由" prop="href" v-if="form.match_type == '1'">
+                  <el-input size="large" v-model="form.href" placeholder="请输入路由" />
+                </el-form-item>
+                <el-form-item label="组织单位" prop="work">
+                  <el-input size="large" v-model="form.work" placeholder="请输入组织单位" />
+                </el-form-item>
+                <el-form-item label="行业" prop="industry">
+                  <el-select v-model="form.type" placeholder="请选择行业" size="large" style="width: 100%">
+                    <el-option v-for="item in industryList" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="奖金(万元)" prop="money">
+                  <el-input size="large" v-model="form.money" placeholder="请输入奖金(万元)" />
+                </el-form-item>
+                <el-form-item label="有效期" prop="time">
+                  <el-date-picker v-model="form.time" type="datetimerange" start-placeholder="开始日期" end-placeholder="结束日期" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"> </el-date-picker>
+                </el-form-item>
+                <el-form-item label="是否启用" prop="is_use">
+                  <el-radio-group v-model="form.is_use">
+                    <el-radio v-for="item in isUseList" :key="item.value" :value="item.value" size="large">{{ item.label }}</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+                <el-form-item label="是否公开路演人信息" prop="is_show" v-if="form.form == '3'">
+                  <el-radio-group v-model="form.is_show">
+                    <el-radio v-for="item in isUseList" :key="item.value" :value="item.value" size="large">{{ item.label }}</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+                <el-form-item label="视频" prop="vide">
+                  <custom-upload model="video" :list="form.video" :limit="1" url="/files/web/cxyy_match/upload" @change="onUpload"></custom-upload>
+                </el-form-item>
+                <el-form-item label="地址" prop="address">
+                  <el-input size="large" v-model="form.address" type="textarea" placeholder="请输入地址" />
+                </el-form-item>
+                <el-form-item label="备注" prop="remark">
+                  <el-input size="large" v-model="form.remark" type="textarea" placeholder="请输入备注" />
+                </el-form-item>
+              </el-tab-pane>
+              <el-tab-pane label="拓展信息" name="second">
+                <el-form-item label="" prop="file">
                   <div class="rules">
                     <custom-form v-model="form.rules" :fields="rulesFields" :useSave="false">
                       <template #rules1>
@@ -129,15 +163,13 @@
                       </template>
                     </custom-form>
                   </div>
-                </template>
-                <template #brief>
+                </el-form-item>
+                <el-form-item label="简介" prop="brief">
                   <WangEditor v-model="form.brief" />
-                </template>
-              </custom-form>
-            </el-tab-pane>
-            <el-tab-pane label="流程信息" name="third">
-              <custom-form v-model="form" :fields="thrformFields" :rules="{}" @save="toSave" @draftSave="toDraftSave">
-                <template #process>
+                </el-form-item>
+              </el-tab-pane>
+              <el-tab-pane label="流程信息" name="third">
+                <el-form-item label="" prop="process">
                   <el-col :span="24" class="tables">
                     <el-col :span="24" class="tables_1">
                       <el-button type="primary" @click="addProcess()">添加</el-button>
@@ -170,29 +202,55 @@
                       </el-table>
                     </el-col>
                   </el-col>
-                </template>
-              </custom-form>
-            </el-tab-pane>
-            <el-tab-pane label="报名信息设置" name="fourth" v-if="form.form == '4'">
-              <el-col :span="24" class="add">
-                <el-button type="primary" @click="addInvest()">添加</el-button>
-              </el-col>
-              <el-table :data="investigateList" border>
-                <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
-                <el-table-column prop="problem" label="问题" align="center"> </el-table-column>
-                <el-table-column label="操作" align="center" width="200">
-                  <template #default="scope">
-                    <el-button size="mini" type="primary" @click="updateInvest(scope.row)">修改</el-button>
-                    <el-button size="mini" type="danger" @click="delInvest(scope.row)">删除</el-button>
-                  </template>
-                </el-table-column>
-              </el-table>
-              <div class="button">
-                <el-button type="warning" @click="InvestSave('-2')">保存草稿</el-button>
-                <el-button type="primary" @click="InvestSave('0')">保存并提交审核</el-button>
-              </div>
-            </el-tab-pane>
-          </el-tabs>
+                </el-form-item>
+              </el-tab-pane>
+              <el-tab-pane label="报名信息设置" name="fourth" v-if="form.form == '4'">
+                <el-form-item label="" prop="ext_info">
+                  <el-col :span="24" class="add">
+                    <el-button type="primary" @click="addInvest()">添加</el-button>
+                  </el-col>
+                  <el-table :data="investigateList" border>
+                    <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
+                    <el-table-column prop="problem" label="字段名称" align="center"> </el-table-column>
+                    <el-table-column label="操作" align="center" width="200">
+                      <template #default="scope">
+                        <el-button type="primary" @click="updateInvest(scope.row)">修改</el-button>
+                        <el-button size="mini" type="danger" @click="delInvest(scope.row)">删除</el-button>
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                </el-form-item>
+              </el-tab-pane>
+              <el-tab-pane label="分数纬度设置" name="fifth" v-if="form.form == '4'">
+                <el-form-item label="" prop="ext_finals">
+                  <el-col :span="24" class="tables">
+                    <el-col :span="24" class="tables_1">
+                      <el-button type="primary" @click="addFinals()">添加</el-button>
+                    </el-col>
+                    <el-col :span="24">
+                      <el-table :data="finalsList" border>
+                        <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
+                        <el-table-column prop="name" label="纬度名称" align="center">
+                          <template #default="scope">
+                            <el-input v-model="scope.row.name" placeholder="请输入纬度名称" />
+                          </template>
+                        </el-table-column>
+                        <el-table-column label="操作" align="center" width="100">
+                          <template #default="scope">
+                            <el-button type="danger" @click="delFinals(scope.row)">删除</el-button>
+                          </template>
+                        </el-table-column>
+                      </el-table>
+                    </el-col>
+                  </el-col>
+                </el-form-item>
+              </el-tab-pane>
+            </el-tabs>
+            <el-col :span="24" class="button">
+              <el-button type="warning" size="large" @click="toDraftSave(formRef)">保存草稿</el-button>
+              <el-button type="primary" size="large" @click="toSave(formRef)">保存并提交审核</el-button>
+            </el-col>
+          </el-form>
         </el-col>
         <el-col :span="24" v-if="dialog.type == '2'">
           <sign :matchForm="form"></sign>
@@ -210,15 +268,27 @@
         <el-col :span="24" v-if="dialog.type == '5'">
           <preliminary :matchForm="form"></preliminary>
         </el-col>
+        <el-col :span="24" v-if="dialog.type == '6'">
+          <extOne :matchForm="form" :type="1" @toClose="toClose"></extOne>
+        </el-col>
+        <el-col :span="24" v-if="dialog.type == '7'">
+          <extOne :matchForm="form" :type="2" @toClose="toClose"></extOne>
+        </el-col>
+        <el-col :span="24" v-if="dialog.type == '8'">
+          <extOne :matchForm="form" :type="3" @toClose="toClose"></extOne>
+        </el-col>
+        <el-col :span="24" v-if="dialog.type == '9'">
+          <extOne :matchForm="form" :type="4" @toClose="toClose"></extOne>
+        </el-col>
       </el-row>
     </el-dialog>
-    <el-dialog v-model="dialogVisible" title="调查问卷填写" width="800" :destroy-on-close="false" @close="toInvestClose">
+    <el-dialog v-model="dialogVisible" title="报名信息填写" width="800" :destroy-on-close="false" @close="toInvestClose">
       <custom-form v-model="investigateForm" :fields="fourformFields" :rules="fourRules" @save="toInvestigateSave" submitText="保存" :DraftSave="false">
         <template #type>
           <el-option v-for="i in proTypeList" :key="i.value" :label="i.label" :value="i.value"></el-option>
         </template>
         <template #answer>
-          <div class="answer" v-if="investigateForm.type == '0' || investigateForm.type == '1' || investigateForm.type == '2' || investigateForm.type == '6'">
+          <div class="answer" v-if="investigateForm.type == '0' || investigateForm.type == '1' || investigateForm.type == '2' || investigateForm.type == '7'">
             <el-col :span="24" class="add">
               <el-button type="primary" @click="addAnswer()">添加</el-button>
             </el-col>
@@ -236,8 +306,8 @@
               </el-table-column>
             </el-table>
           </div>
-          <div class="answer" v-if="investigateForm.type == '7'">
-            <custom-upload model="file" :list="answerFile" :limit="1" url="/files/web/cxyy_match/upload" @change="onaUpload"></custom-upload>
+          <div class="answer" v-if="investigateForm.type == '8'">
+            <custom-upload model="file" :list="answerFile" accept="*" :limit="10" url="/files/web/cxyy_match/upload" @change="onaUpload"></custom-upload>
           </div>
         </template>
         <template #is_must>
@@ -254,6 +324,7 @@ import moment from 'moment'
 import sign from './parts/sign.vue'
 import score from './parts/score.vue'
 import preliminary from './parts/preliminaryMatch.vue'
+import extOne from './parts/extOne.vue'
 import { Search } from '@element-plus/icons-vue'
 import { cloneDeep, get } from 'lodash-es'
 const $checkRes = inject('$checkRes')
@@ -292,35 +363,13 @@ const scaleList = ref([])
 
 // 流程列表
 const processList = ref([])
-
-const form = ref({ time: [], rules: {} })
+// 表单
+const formRef = ref()
+const form = ref({ video: [], time: [], rules: {} })
 const dialog = ref({ type: '1', show: false, title: '发布赛事' })
 const activeName = ref('first')
-const oneformFields = ref([
-  { label: '封面', model: 'file', custom: true },
-  { label: '赛事名称', model: 'name' },
-  { label: '类别', model: 'form', type: 'select' },
-  { label: '标签', model: 'tags', custom: true },
-  { label: '类型', model: 'type', type: 'select' },
-  { label: '赛事规模', model: 'scale', type: 'radio' },
-  { label: '赛事类型', model: 'match_type', type: 'radio' },
-  { label: '路由', model: 'href', display: () => form.value.match_type == '1' },
-  { label: '组织单位', model: 'work' },
-  { label: '行业', model: 'industry', type: 'select' },
-  { label: '奖金(万元)', model: 'money' },
-  { label: '有效期', model: 'time', type: 'datetimerange' },
-  { label: '是否启用', model: 'is_use', type: 'radio' },
-  { label: '是否公开路演人信息', model: 'is_show', type: 'radio' },
-  { label: '视频', model: 'video', custom: true },
-  { label: '地址', model: 'address', type: 'textarea' },
-  { label: '备注', model: 'remark', type: 'textarea', display: () => form.value.form == '3' }
-])
-const twoformFields = ref([
-  { model: 'rules', custom: true },
-  { label: '简介', model: 'brief', custom: true }
-])
-const thrformFields = ref([{ label: '赛事流程', model: 'process', custom: true }])
-
+// 分数纬度列表
+const finalsList = ref([])
 const matchFields = ref([{ label: '赛事状态', model: 'match_status', type: 'select' }])
 const matchRules = reactive({ match_status: [{ required: true, message: '请选择赛事状态', trigger: 'blur' }] })
 const rules = reactive({
@@ -349,30 +398,31 @@ const rulesFields = ref([
 const investigateList = ref([])
 const investigateForm = ref({})
 const fourformFields = ref([
-  { label: '问题', model: 'problem' },
+  { label: '字段名称', model: 'problem' },
   { label: '类型', model: 'type', type: 'select' },
   {
     label: '答案',
     model: 'answer',
     custom: true,
-    display: () => investigateForm.value.type == '0' || investigateForm.value.type == '1' || investigateForm.value.type == '2' || investigateForm.value.type == '6' || investigateForm.value.type == '7'
+    display: () => investigateForm.value.type == '0' || investigateForm.value.type == '1' || investigateForm.value.type == '2' || investigateForm.value.type == '7' || investigateForm.value.type == '8'
   },
-  { label: '是否必填', model: 'is_must', type: 'radio' },
+  { label: '是否必填', model: 'is_must', type: 'radio', display: () => investigateForm.value.type != '7' },
   { label: '备注', model: 'remark', type: 'textarea' }
 ])
 const fourRules = reactive({
-  problem: [{ required: true, message: '请输入问题', trigger: 'blur' }]
+  problem: [{ required: true, message: '请输入字段名称', trigger: 'blur' }]
 })
 const dialogVisible = ref(false)
 const proTypeList = ref([
   { value: '0', label: '单选' },
   { value: '1', label: '多选' },
   { value: '2', label: '下拉' },
-  { value: '3', label: '单行文本' },
-  { value: '4', label: '多行文本' },
-  { value: '5', label: '图片/文件' },
-  { value: '6', label: '数组' },
-  { value: '7', label: '附件模板' }
+  { value: '3', label: '数值类型' },
+  { value: '4', label: '单行文本' },
+  { value: '5', label: '多行文本' },
+  { value: '6', label: '图片/文件' },
+  { value: '7', label: '数组' },
+  { value: '8', label: '附件模板' }
 ])
 // 答案
 const answerList = ref([])
@@ -453,6 +503,7 @@ const toEdit = async (data) => {
     res.data.time = [data.start_time, data.end_time]
     form.value = res.data
     if (res.data.ext_info && res.data.ext_info.length > 0) investigateList.value = res.data.ext_info
+    if (res.data.ext_finals && res.data.ext_finals.length > 0) finalsList.value = res.data.ext_finals
     await searchProcess()
     dialog.value = { type: '1', show: true, title: '修改赛事' }
   }
@@ -477,6 +528,11 @@ const toPreliminary = (data) => {
   form.value = data
   dialog.value = { type: '5', show: true, title: '初赛信息' }
 }
+// 赛事设置
+const toExtOne = (data) => {
+  form.value = data
+  window.open(`/cxyyMatch/home/?id=${data.id || data._id}`)
+}
 // 删除
 const toDelete = (data) => {
   ElMessageBox.confirm(`您确认删除${data.name}该数据?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
@@ -488,41 +544,77 @@ const toDelete = (data) => {
     })
     .catch(() => {})
 }
-const toSave = async () => {
-  const data = cloneDeep(form.value)
-  const other = { status: '0', user: user.value.id }
-  if (data.time && data.time.length > 1) {
-    data.start_time = data.time[0]
-    data.end_time = data.time[1]
-  }
-  delete data.time
-  let res
-  if (get(data, 'id')) res = await store.update({ ...data, ...other })
-  else res = await store.create({ ...data, ...other })
-  if ($checkRes(res, true)) {
-    if (res.data && res.data.id) match_id.value = res.data.id
-    await toProcessSave()
-    await search({ skip, limit })
-    toClose()
-  }
-}
-const toDraftSave = async () => {
-  const data = cloneDeep(form.value)
-  const other = { status: '-2', user: user.value.id }
-  if (data.time && data.time.length > 1) {
-    data.start_time = data.time[0]
-    data.end_time = data.time[1]
-  }
-  delete data.time
-  let res
-  if (get(data, 'id')) res = await store.update({ ...data, ...other })
-  else res = await store.create({ ...data, ...other })
-  if ($checkRes(res, true)) {
-    if (res.data && res.data.id) match_id.value = res.data.id
-    await toProcessSave()
-    await search({ skip, limit })
-    toClose()
-  }
+const toSave = async (formEl) => {
+  if (!formEl) return
+  await formEl.validate(async (valid) => {
+    if (valid) {
+      const data = cloneDeep(form.value)
+      const other = { status: '0', user: user.value.id }
+      if (data.time && data.time.length > 1) {
+        data.start_time = data.time[0]
+        data.end_time = data.time[1]
+      }
+      delete data.time
+      if (investigateList.value && investigateList.value.length > 0) data.ext_info = investigateList.value
+      if (finalsList.value && finalsList.value.length > 0) data.ext_finals = finalsList.value
+      let res
+      if (get(data, 'id')) res = await store.update({ ...data, ...other })
+      else res = await store.create({ ...data, ...other })
+      if (res.errcode == 0) {
+        ElMessageBox.alert('赛事发布成功,请在中查看赛事发布信息', '赛事发布', {
+          confirmButtonText: '确定',
+          callback: async () => {
+            if (res.data && res.data.id) match_id.value = res.data.id
+            await toProcessSave()
+            form.value = { time: [], rules: {} }
+            processList.value = []
+            activeName.value = 'first'
+          }
+        })
+      }
+    } else {
+      ElMessage({
+        message: '有相关必填项没有填写',
+        type: 'warning'
+      })
+    }
+  })
+}
+const toDraftSave = async (formEl) => {
+  if (!formEl) return
+  await formEl.validate(async (valid) => {
+    if (valid) {
+      const data = cloneDeep(form.value)
+      const other = { status: '-2', user: user.value.id }
+      if (data.time && data.time.length > 1) {
+        data.start_time = data.time[0]
+        data.end_time = data.time[1]
+      }
+      delete data.time
+      if (investigateList.value && investigateList.value.length > 0) data.ext_info = investigateList.value
+      if (finalsList.value && finalsList.value.length > 0) data.ext_finals = finalsList.value
+      let res
+      if (get(data, 'id')) res = await store.update({ ...data, ...other })
+      else res = await store.create({ ...data, ...other })
+      if (res.errcode == 0) {
+        ElMessageBox.alert('赛事发布成功,请在历史发布中选择赛事管理查看发布赛事信息', '赛事发布', {
+          confirmButtonText: '确定',
+          callback: async () => {
+            if (res.data && res.data.id) match_id.value = res.data.id
+            await toProcessSave()
+            form.value = { time: [], rules: {} }
+            processList.value = []
+            activeName.value = 'first'
+          }
+        })
+      }
+    } else {
+      ElMessage({
+        message: '有相关必填项没有填写',
+        type: 'warning'
+      })
+    }
+  })
 }
 // 审核保存
 const toExam = async (row) => {
@@ -531,27 +623,28 @@ const toExam = async (row) => {
       const data = cloneDeep(row)
       let res = await store.update({ id: data.id, status: '0', user: user.value.id })
       if ($checkRes(res, true)) {
-        search({ skip, limit })
         toClose()
       }
     })
     .catch(() => {})
 }
 
-// 修改赛事
+// 修改赛事状态
 const toMatchSave = async (row) => {
   const data = cloneDeep(row)
   let res = await store.update({ id: data.id, match_status: data.match_status })
   if ($checkRes(res, true)) {
-    search({ skip, limit })
     toClose()
   }
 }
-
-const toClose = () => {
+const toClose = async () => {
   form.value = { time: [], rules: {} }
   dialog.value = { show: false }
+  investigateList.value = []
+  finalsList.value = []
+  processList.value = []
   activeName.value = 'first'
+  await search({ skip, limit })
 }
 // 上传图片
 const onUpload = (e) => {
@@ -602,7 +695,10 @@ const addInvest = () => {
 // 调查问卷修改
 const updateInvest = (e) => {
   dialogVisible.value = true
-  if (e.answer && e.answer.length > 0) answerList.value = e.answer
+  if (e.answer && e.answer.length > 0) {
+    if (e.type == '8') answerFile.value = e.answer
+    else answerList.value = e.answer
+  }
   investigateForm.value = e
 }
 // 删除调查问卷
@@ -639,18 +735,16 @@ const delAnswer = async (e) => {
   let list = answerList.value.filter((i) => i.sid != e.sid)
   answerList.value = list
 }
-//  保存并提交审核
-const InvestSave = async (status) => {
-  const data = cloneDeep(form.value)
-  const other = { status, user: user.value.id }
-  let res
-  if (get(data, 'id')) res = await store.update({ id: data.id, ext_info: investigateList.value, ...other, ...data })
-  else res = await store.create({ ext_info: investigateList.value, ...other, ...data })
-  if (res.errcode == 0) {
-    ElMessage({ message: `发布成功可以上历史发布查看`, type: 'success' })
-    search({ skip, limit })
-    toClose()
-  }
+// 维度添加
+const addFinals = () => {
+  let list = finalsList.value || []
+  list.push({ sid: moment().valueOf(), name: '' })
+  finalsList.value = list
+}
+// 维度删除
+const delFinals = async (e) => {
+  let list = finalsList.value.filter((i) => i.sid != e.sid)
+  finalsList.value = list
 }
 // 上传图片
 const onaUpload = (e) => {

+ 256 - 0
src/views/center/news1.vue

@@ -0,0 +1,256 @@
+<template>
+  <div class="index">
+    <el-row>
+      <el-col :span="24" class="main" v-loading="loading">
+        <el-col :span="24" class="one">
+          <div class="one_left" @click="toAdd">发布赛事通知</div>
+          <div class="one_right">
+            <el-input v-model="searchForm.title" style="width: 250px" size="large" placeholder="搜索" @change="search" :suffix-icon="Search" />
+          </div>
+        </el-col>
+        <el-col :span="24" class="two">
+          <el-table :data="list" style="width: 100%" size="large" :header-cell-style="{ backgroundColor: '#edf3ff' }">
+            <template #empty>
+              <el-empty description="暂无数据" />
+            </template>
+            <el-table-column prop="title" align="center" label="标题" />
+            <el-table-column prop="time" align="center" label="发布时间" width="180" />
+            <el-table-column prop="status" align="center" label="状态" width="180">
+              <template #default="scope">
+                <div>{{ getDict(scope.row.status, 'status') }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column align="center" label="操作" width="180">
+              <template #default="{ row }">
+                <el-link v-if="row.status == '-2'" :underline="false" type="warning" size="mini" @click="toExam(row)" style="margin-right: 10px">提交审核</el-link>
+                <el-link :underline="false" type="primary" size="mini" @click="toEdit(row)" style="margin-right: 10px">修改</el-link>
+                <el-link :underline="false" type="danger" size="mini" @click="toDelete(row)"> 删除 </el-link>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-col>
+        <el-col :span="24" class="thr">
+          <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
+        </el-col>
+      </el-col>
+    </el-row>
+    <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose">
+      <el-row>
+        <el-col :span="24" v-if="dialog.type == '1'">
+          <custom-form v-model="form" :fields="formFields" :rules="rules" @save="toSave" @draftSave="toDraftSave">
+            <template #logo>
+              <custom-upload model="logo" :list="form.logo" :limit="1" url="/files/web/cxyy_news/upload" @change="onUpload" listType="picture-card"></custom-upload>
+            </template>
+            <template #is_use>
+              <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+            </template>
+            <template #is_show>
+              <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+            </template>
+            <template #tags>
+              <el-select v-model="form.tags" multiple filterable allow-create default-first-option :reserve-keyword="false" placeholder="请选择标签" style="width: 100%">
+                <el-option v-for="item in tagsList" :key="item.id" :label="item.title" :value="item.title" />
+              </el-select>
+            </template>
+            <template #content>
+              <WangEditor v-model="form.content" />
+            </template>
+          </custom-form>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import moment from 'moment'
+import { Search } from '@element-plus/icons-vue'
+import { cloneDeep, get } from 'lodash-es'
+const $checkRes = inject('$checkRes')
+import { UserStore } from '@/store/user'
+const userStore = UserStore()
+const user = computed(() => userStore.user)
+// 接口
+import { NewsStore } from '@/store/api/platform/news'
+import { DictDataStore } from '@/store/api/system/dictData'
+import { TagsStore } from '@/store/api/system/tags'
+const store = NewsStore()
+const dictDataStore = DictDataStore()
+const tagsStore = TagsStore()
+// 加载中
+const loading = ref(false)
+
+const searchForm = ref({})
+// 列表
+const list = ref([])
+let skip = 0
+let limit = inject('limit')
+const total = ref(0)
+const currentPage = ref(1)
+// 字典表
+const isUseList = ref([])
+const statusList = ref([])
+const tagsList = ref([])
+
+const form = ref({ logo: [], type: '1' })
+const dialog = ref({ type: '1', show: false, title: '发布行业动态' })
+const formFields = ref([
+  { label: '封面', model: 'logo', custom: true },
+  { label: '标题', model: 'title' },
+  { label: '标签', model: 'tags', custom: true },
+  { label: '发布人', model: 'person', options: { disabled: true } },
+  { label: '发布时间', model: 'time', type: 'date', options: { disabled: true } },
+  { label: '浏览量', model: 'number', options: { disabled: true } },
+  { label: '是否公开', model: 'is_use', type: 'radio' },
+  { label: '是否在首页显示', model: 'is_show', type: 'radio' },
+  { label: '内容', model: 'content', custom: true }
+])
+const rules = reactive({
+  logo: [{ required: true, message: '请上传封面', trigger: 'blur' }],
+  name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
+  content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
+})
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search()
+  loading.value = false
+})
+const search = async (query = { skip, limit }) => {
+  skip = query.skip
+  limit = query.limit
+  const info = {
+    skip: query.skip,
+    limit: query.limit,
+    user: user.value.id,
+    type: '1',
+    ...searchForm.value
+  }
+  const res = await store.query(info)
+  if (res.errcode == '0') {
+    list.value = res.data
+    total.value = res.total
+  }
+}
+const searchOther = async () => {
+  let result
+  // 是否使用
+  result = await dictDataStore.query({ code: 'isUse', is_use: '0' })
+  if ($checkRes(result)) isUseList.value = result.data
+  // 状态
+  result = await dictDataStore.query({ code: 'examStatus', is_use: '0' })
+  if ($checkRes(result)) statusList.value = result.data
+  // 标签
+  result = await tagsStore.query({ is_use: '0' })
+  if ($checkRes(result)) tagsList.value = result.data
+}
+// 字典数据转换
+const getDict = (data, model) => {
+  if (data) {
+    let res
+    if (model == 'status') res = statusList.value.find((f) => f.value == data)
+    return get(res, 'label')
+  }
+}
+// 添加
+const toAdd = () => {
+  form.value = { status: '0', type: '1', user: user.value.id, time: moment().format('YYYY-MM-DD'), person: user.value.nick_name }
+  dialog.value = { type: '1', show: true, title: '发布行业动态' }
+}
+// 修改
+const toEdit = (data) => {
+  form.value = data
+  dialog.value = { type: '1', show: true, title: '修改行业动态' }
+}
+// 删除
+const toDelete = (data) => {
+  ElMessageBox.confirm(`您确认删除${data.name}该数据?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
+    .then(async () => {
+      const res = await store.del(data.id)
+      if ($checkRes(res, true)) {
+        search({ skip, limit })
+      }
+    })
+    .catch(() => {})
+}
+const toSave = async () => {
+  const data = cloneDeep(form.value)
+  const other = { status: '0', type: '1', user: user.value.id, time: moment().format('YYYY-MM-DD'), person: user.value.nick_name }
+  let res
+  if (get(data, 'id')) res = await store.update({ ...data, ...other })
+  else res = await store.create({ ...data, ...other })
+  if ($checkRes(res, true)) {
+    search({ skip, limit })
+    toClose()
+  }
+}
+const toDraftSave = async () => {
+  const data = cloneDeep(form.value)
+  const other = { status: '-2', type: '1', user: user.value.id, time: moment().format('YYYY-MM-DD'), person: user.value.nick_name }
+  let res
+  if (get(data, 'id')) res = await store.update({ ...data, ...other })
+  else res = await store.create({ ...data, ...other })
+  if ($checkRes(res, true)) {
+    search({ skip, limit })
+    toClose()
+  }
+}
+// 审核保存
+const toExam = async (row) => {
+  ElMessageBox.confirm(`您确认保存并提交审核该数据?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
+    .then(async () => {
+      const data = cloneDeep(row)
+      let res = await store.update({ id: data.id, status: '0', user: user.value.id })
+      if ($checkRes(res, true)) {
+        search({ skip, limit })
+        toClose()
+      }
+    })
+    .catch(() => {})
+}
+const toClose = () => {
+  form.value = { logo: [], type: '1' }
+  dialog.value = { show: false }
+}
+// 上传图片
+const onUpload = (e) => {
+  const { model, value } = e
+  form.value[model] = value
+}
+// 分页
+const changePage = (page = currentPage.value) => {
+  search({ skip: (page - 1) * limit, limit: limit })
+}
+const sizeChange = (limits) => {
+  limit = limits
+  currentPage.value = 1
+  search({ skip: 0, limit: limit })
+}
+</script>
+<style scoped lang="scss">
+.main {
+  .one {
+    height: 50px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin: 0 0 10px 0;
+    .one_left {
+      background: #1875df;
+      padding: 0 10px;
+      height: 30px;
+      color: #fff;
+      line-height: 30px;
+      text-align: center;
+      font-size: 16px;
+      cursor: default;
+    }
+  }
+  .thr {
+    display: flex;
+    justify-content: center;
+    margin: 20px 0 0 0;
+  }
+}
+</style>

+ 74 - 0
src/views/center/parts/extOne.vue

@@ -0,0 +1,74 @@
+<template>
+  <div class="index">
+    <div v-if="type == '1'">
+      <el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="auto" class="form" label-position="left">
+        <el-form-item label="初赛开始时间" prop="start_time">
+          <el-date-picker format="YYYY-MM-DD" value-format="YYYY-MM-DD" v-model="form.start_time" type="date" placeholder="请选择初赛开始时间" style="width: 100%" />
+        </el-form-item>
+        <el-col :span="24" class="button">
+          <el-button type="primary" @click="submitForm(ruleFormRef)">保存</el-button>
+        </el-col>
+      </el-form>
+    </div>
+    <div v-if="type == '2'">决赛准备</div>
+    <div v-if="type == '3'">决赛开始</div>
+    <div v-if="type == '4'">决赛结束</div>
+  </div>
+</template>
+<script setup>
+import { cloneDeep } from 'lodash-es'
+const $checkRes = inject('$checkRes')
+const id = ref('')
+const props = defineProps({
+  matchForm: { type: Object },
+  type: { type: String }
+})
+const match = computed({
+  get() {
+    return props.matchForm
+  }
+})
+const emits = defineEmits(['toClose'])
+// 接口
+import { MatchExtStore } from '@/store/api/platform/matchExt'
+const store = MatchExtStore()
+
+const form = ref({})
+// 表单
+const ruleFormRef = ref()
+const rules = reactive({
+  start_time: [{ required: true, message: '请选择初赛开始时间', trigger: 'blur' }]
+})
+// 保存
+const submitForm = async (formEl) => {
+  if (!formEl) return
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      const data = cloneDeep(form.value)
+      data.id = id.value
+      const res = await store.firstStep(data)
+      if ($checkRes(res, true)) {
+        emits('toClose')
+      } else ElMessage.error(res.message)
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+watch(
+  match,
+  async (item) => {
+    id.value = item.id
+  },
+  {
+    immediate: true //初始化立即执行
+  }
+)
+</script>
+<style scoped lang="scss">
+.index {
+  .button {
+    text-align: center;
+  }
+}
+</style>

+ 69 - 19
src/views/center/parts/preliminaryMatch.vue

@@ -1,43 +1,50 @@
 <template>
   <div class="main" v-loading="loading">
     <el-col :span="24" class="one">
-      <el-table :data="list" style="width: 100%" size="large" :header-cell-style="{ backgroundColor: '#edf3ff' }">
+      <div class="one_left" @click="toExport">导出</div>
+    </el-col>
+    <el-col :span="24" class="two">
+      <el-table :data="list" style="width: 100%" size="large" :header-cell-style="{ backgroundColor: '#edf3ff' }" @selection-change="handleSelectionChange">
         <template #empty>
           <el-empty description="暂无数据" />
         </template>
+        <el-table-column type="selection" :selectable="handleRowSelectable" width="55"> </el-table-column>
         <el-table-column prop="no" align="center" label="编号" width="100"> </el-table-column>
         <el-table-column prop="user_name" align="center" label="用户"> </el-table-column>
         <el-table-column prop="time" align="center" label="报名时间" />
         <el-table-column prop="status" align="center" label="状态" width="100">
           <template #default="scope">
-            <el-tag v-if="scope.row.status == '0'" type="success">符合要求</el-tag>
+            <el-tag v-if="scope.row.status == '0'" type="primary">待审核</el-tag>
+            <el-tag v-else-if="scope.row.status == '1'" type="success">已通过</el-tag>
             <el-tag v-else type="info">已退回</el-tag>
           </template>
         </el-table-column>
         <el-table-column align="center" label="操作" width="180">
           <template #default="{ row }">
-            <el-link v-if="row.status == '0'" :underline="false" type="warning" size="mini" @click="toView(row)" style="margin-right: 10px">审核</el-link>
+            <el-link :underline="false" type="primary" size="mini" @click="toView(row, true)" style="margin-right: 10px">查看</el-link>
+            <el-link v-if="row.status == '0'" :underline="false" type="warning" size="mini" @click="toView(row, false)" style="margin-right: 10px">报名审核</el-link>
           </template>
         </el-table-column>
       </el-table>
     </el-col>
-    <el-col :span="24" class="two">
+    <el-col :span="24" class="thr">
       <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
     </el-col>
     <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose">
-      <el-descriptions title="报名信息" :column="1" border>
-        <template #extra>
-          <el-button type="danger" @click="toExam">退回报名申请</el-button>
+      <el-descriptions title="" :column="1" border>
+        <template #extra v-if="!is_look">
+          <el-button type="primary" @click="toExam('1')">通过申请</el-button>
+          <el-button type="danger" @click="toExam('2')">退回申请</el-button>
         </template>
         <el-descriptions-item v-for="(item, index) in info" :key="index" :label="item.problem">
-          <div class="type" v-if="item.type == '0' || item.type == '2' || item.type == '3' || item.type == '4'">{{ item.reply || '暂无内容' }}</div>
-          <div class="type" v-if="item.type == '1'">{{ item.reply.join(',') }}</div>
-          <div class="type" v-if="item.type == '5'">
+          <div class="type" v-if="item.type == '0' || item.type == '2' || item.type == '3' || item.type == '4' || item.type == '5'">{{ item.reply || '暂无内容' }}</div>
+          <div class="type" v-if="item.type == '1' && item.reply">{{ item.reply.join(',') }}</div>
+          <div class="type" v-if="item.type == '6'">
             <div v-for="(as, img) in item.reply" :key="img">
               <el-link :href="getUrl(as)" target="_blank">{{ as.name }}</el-link>
             </div>
           </div>
-          <div class="type" v-if="item.type == '6'">
+          <div class="type" v-if="item.type == '7'">
             <div class="list">
               <div v-for="(aa, ina) in item.answer" :key="ina" class="name">{{ aa.text }}</div>
             </div>
@@ -47,7 +54,7 @@
               </div>
             </div>
           </div>
-          <div class="type" v-if="item.type == '7'">
+          <div class="type" v-if="item.type == '8'">
             <div v-for="(as, img) in item.answer" :key="img">
               <el-link :href="getUrl(as)" target="_blank">{{ as.name }}</el-link>
             </div>
@@ -85,8 +92,11 @@ const currentPage = ref(1)
 const info = ref([])
 
 const form = ref({})
-const dialog = ref({ type: '1', show: false, title: '审核报名信息' })
+const dialog = ref({ type: '1', show: false, title: '报名信息' })
 
+// 批量导出
+const selectionList = ref([])
+const is_look = ref(false)
 const search = async (query = { skip, limit }) => {
   skip = query.skip
   limit = query.limit
@@ -101,26 +111,33 @@ const search = async (query = { skip, limit }) => {
     total.value = res.total
   }
 }
+const handleSelectionChange = (val) => {
+  selectionList.value = val
+}
 // 审核
-const toView = (data) => {
+const toView = (data, is_no) => {
+  is_look.value = is_no
   form.value = data
   info.value = data.info
-  dialog.value = { type: '1', show: true, title: '审核报名信息' }
+  dialog.value = { type: '1', show: true, title: '报名信息' }
 }
 // 图片处理
 const getUrl = (e) => {
   if (e) return `${import.meta.env.VITE_APP_HOST}${get(e, 'uri')}`
 }
 // 审核
-const toExam = () => {
-  ElMessageBox.confirm('确定将该报名信息退回?', '审核信息', {
+const toExam = (status) => {
+  let title
+  if (status == '1') title = '确定将该通过该申请的报名信息?'
+  else title = '确定将退回该申请的报名信息?'
+  ElMessageBox.confirm(title, '审核信息', {
     confirmButtonText: '确认',
     cancelButtonText: '取消',
     type: 'warning'
   })
     .then(async () => {
       const data = form.value
-      const res = await store.update({ id: data.id, status: '-1' })
+      const res = await store.update({ id: data.id, status })
       if ($checkRes(res, true)) {
         toClose()
       }
@@ -136,7 +153,23 @@ const sizeChange = (limits) => {
   currentPage.value = 1
   search({ skip: 0, limit: limit })
 }
+// 根据数据项中的canSelect字段判断是否可选
+const handleRowSelectable = (row) => {
+  return row.status == '0'
+}
+// 导出
+const toExport = () => {
+  if (selectionList.value && selectionList.value.length > 0) {
+    console.log('导出')
+  } else {
+    ElMessage({
+      message: '请选择要导出的数据!',
+      type: 'warning'
+    })
+  }
+}
 const toClose = async () => {
+  is_look.value = false
   form.value = {}
   dialog.value = { show: false }
   await search({ skip, limit })
@@ -156,7 +189,24 @@ watch(
 </script>
 <style scoped lang="scss">
 .main {
-  .two {
+  .one {
+    height: 50px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin: 0 0 10px 0;
+    .one_left {
+      background: #1875df;
+      padding: 0 10px;
+      height: 30px;
+      color: #fff;
+      line-height: 30px;
+      text-align: center;
+      font-size: 16px;
+      cursor: default;
+    }
+  }
+  .thr {
     display: flex;
     justify-content: center;
     margin: 20px 0 0 0;

+ 166 - 55
src/views/center/parts/preliminaryUser.vue

@@ -6,7 +6,7 @@
           <el-empty description="暂无数据" />
         </template>
         <el-table-column prop="no" align="center" label="编号" width="100"> </el-table-column>
-        <el-table-column prop="user_name" align="center" label="用户"> </el-table-column>
+        <el-table-column prop="match_name" align="center" label="赛事名称" />
         <el-table-column prop="time" align="center" label="报名时间" />
         <el-table-column prop="status" align="center" label="状态" width="100">
           <template #default="scope">
@@ -16,7 +16,9 @@
         </el-table-column>
         <el-table-column align="center" label="操作" width="180">
           <template #default="{ row }">
-            <el-link v-if="row.status == '-1'" :underline="false" type="warning" size="mini" @click="toEdit(row)" style="margin-right: 10px">修改</el-link>
+            <el-link :underline="false" type="primary" size="mini" @click="toView(row)" style="margin-right: 10px">查看</el-link>
+            <el-link v-if="row.status == '-1'" :underline="false" type="warning" size="mini" @click="toEdit(row)" style="margin-right: 10px">重新提交</el-link>
+            <el-link :underline="false" type="primary" size="mini" @click="toFinals(row)">决赛时间确认</el-link>
           </template>
         </el-table-column>
       </el-table>
@@ -25,65 +27,116 @@
       <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
     </el-col>
     <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose">
-      <div class="list" v-for="(item, index) in investigate" :key="index">
-        <div class="problem">
-          <el-icon v-if="item.is_must == '0'" color="red"><StarFilled /></el-icon>
-          <span style="margin: 0 0 0 10px" v-if="item.is_must == '0'">{{ item.problem }}</span>
-          <span style="margin: 0 0 0 10px" v-else>{{ item.problem }}</span>
-        </div>
-        <div class="type" v-if="item.type == '0'">
-          <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <el-radio-group v-model="item.reply">
-            <el-radio v-for="(i, radio) in item.answer" :key="radio" :value="i.text">{{ i.text }}</el-radio>
-          </el-radio-group>
-        </div>
-        <div class="type" v-if="item.type == '1'">
-          <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <el-checkbox-group v-model="checkbox" @change="checkChange($event, item)">
-            <el-checkbox v-for="(i, checkbox) in item.answer" :key="checkbox" :label="i.text" :value="i.text">
-              {{ i.text }}
-            </el-checkbox>
-          </el-checkbox-group>
-        </div>
-        <div class="type" v-if="item.type == '2'">
-          <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <el-select v-model="item.reply" placeholder="请选择" size="large" style="width: 100%">
-            <el-option v-for="(i, select) in item.answer" :key="select" :label="i.text" :value="i.text" />
-          </el-select>
-        </div>
-        <div class="type" v-if="item.type == '3'">
-          <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <el-input size="large" v-model="item.reply" :placeholder="getField(item.problem)" />
-        </div>
-        <div class="type" v-if="item.type == '4'">
-          <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <el-input v-model="item.reply" type="textarea" :placeholder="getField(item.problem)" />
-        </div>
-        <div class="type" v-if="item.type == '5'">
-          <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <custom-upload model="reply" :list="file" :limit="1" url="/files/web/cxyy_match/upload" @change="onUpload($event, item)"></custom-upload>
-        </div>
-        <div class="type" v-if="item.type == '6'">
-          <div class="list">
-            <div v-for="(aa, ina) in item.answer" :key="ina" class="name">{{ aa.text }}</div>
+      <div v-if="dialog.type == '1'">
+        <div class="list" v-for="(item, index) in investigate" :key="index">
+          <div class="problem">
+            <el-icon v-if="item.is_must == '0'" color="red"><StarFilled /></el-icon>
+            <span style="margin: 0 0 0 10px" v-if="item.is_must == '0'">{{ item.problem }}</span>
+            <span style="margin: 0 0 0 10px" v-else>{{ item.problem }}</span>
+          </div>
+          <div class="type" v-if="item.type == '0'">
+            <div class="remark" v-if="item.remark">{{ item.remark }}</div>
+            <el-radio-group v-model="item.reply">
+              <el-radio v-for="(i, radio) in item.answer" :key="radio" :value="i.text">{{ i.text }}</el-radio>
+            </el-radio-group>
+          </div>
+          <div class="type" v-if="item.type == '1'">
+            <div class="remark" v-if="item.remark">{{ item.remark }}</div>
+            <el-checkbox-group v-model="checkbox" @change="checkChange($event, item)">
+              <el-checkbox v-for="(i, checkbox) in item.answer" :key="checkbox" :label="i.text" :value="i.text">
+                {{ i.text }}
+              </el-checkbox>
+            </el-checkbox-group>
+          </div>
+          <div class="type" v-if="item.type == '2'">
+            <div class="remark" v-if="item.remark">{{ item.remark }}</div>
+            <el-select v-model="item.reply" placeholder="请选择" size="large" style="width: 100%">
+              <el-option v-for="(i, select) in item.answer" :key="select" :label="i.text" :value="i.text" />
+            </el-select>
           </div>
-          <div class="list" v-for="(gg, inx) in item.reply" :key="inx">
-            <div v-for="(aa, ina) in item.answer" :key="ina" class="input">
-              <el-input size="large" v-model="gg[aa.text]" :placeholder="getField(item.problem)" />
+          <div class="type" v-if="item.type == '3'">
+            <div class="remark" v-if="item.remark">{{ item.remark }}</div>
+            <el-input size="large" v-model="item.reply" type="number" :placeholder="getField(item.problem)" />
+          </div>
+          <div class="type" v-if="item.type == '4'">
+            <div class="remark" v-if="item.remark">{{ item.remark }}</div>
+            <el-input size="large" v-model="item.reply" :placeholder="getField(item.problem)" />
+          </div>
+          <div class="type" v-if="item.type == '5'">
+            <div class="remark" v-if="item.remark">{{ item.remark }}</div>
+            <el-input v-model="item.reply" type="textarea" :placeholder="getField(item.problem)" />
+          </div>
+          <div class="type" v-if="item.type == '6'">
+            <div class="remark" v-if="item.remark">{{ item.remark }}</div>
+            <custom-upload model="reply" :list="file" :limit="1" url="/files/web/cxyy_match/upload" @change="onUpload($event, item)"></custom-upload>
+          </div>
+          <div class="type" v-if="item.type == '7'">
+            <div class="list">
+              <div v-for="(aa, ina) in item.answer" :key="ina" class="name">{{ aa.text }}</div>
+            </div>
+            <div class="list" v-for="(gg, inx) in item.reply" :key="inx">
+              <div v-for="(aa, ina) in item.answer" :key="ina" class="input">
+                <el-input size="large" v-model="gg[aa.text]" :placeholder="getField(item.problem)" />
+              </div>
+              <el-icon class="icon" size="25" @click="toDel(item, gg.sid)"><Close /></el-icon>
             </div>
-            <el-icon class="icon" size="25" @click="toDel(item, gg.sid)"><Close /></el-icon>
+            <div class="add" @click="toAdd(item)">+新增一行</div>
           </div>
-          <div class="add" @click="toAdd(item)">+新增一行</div>
-        </div>
-        <div class="type" v-if="item.type == '7'">
-          <div v-for="(as, img) in item.answer" :key="img">
-            <el-link :href="getUrl(as)" target="_blank">{{ as.name }}</el-link>
+          <div class="type" v-if="item.type == '8'">
+            <div v-for="(as, img) in item.answer" :key="img">
+              <el-link :href="getUrl(as)" target="_blank">{{ as.name }}</el-link>
+            </div>
+            <div class="remark" v-if="item.remark">{{ item.remark }}</div>
           </div>
-          <div class="remark" v-if="item.remark">{{ item.remark }}</div>
         </div>
+        <div class="button" v-if="!is_look">
+          <el-button type="primary" @click="toSave()">保存</el-button>
+        </div>
+      </div>
+      <div v-if="dialog.type == '2'">
+        <div class="status">
+          <el-steps :active="active" align-center finish-status="success">
+            <el-step title="报名" />
+            <el-step title="初审" />
+            <el-step title="决赛" />
+          </el-steps>
+        </div>
+        <el-descriptions title="" :column="1" border>
+          <el-descriptions-item v-for="(item, index) in form.info" :key="index" :label="item.problem">
+            <div class="type" v-if="item.type == '0' || item.type == '2' || item.type == '3' || item.type == '4' || item.type == '5'">{{ item.reply || '暂无内容' }}</div>
+            <div class="type" v-if="item.type == '1' && item.reply">{{ item.reply.join(',') }}</div>
+            <div class="type" v-if="item.type == '6'">
+              <div v-for="(as, img) in item.reply" :key="img">
+                <el-link :href="getUrl(as)" target="_blank">{{ as.name }}</el-link>
+              </div>
+            </div>
+            <div class="type" v-if="item.type == '7'">
+              <div class="list">
+                <div v-for="(aa, ina) in item.answer" :key="ina" class="name">{{ aa.text }}</div>
+              </div>
+              <div class="list" v-for="(gg, inx) in item.reply" :key="inx">
+                <div v-for="(aa, ina) in item.answer" :key="ina" class="input">
+                  {{ gg[aa.text] }}
+                </div>
+              </div>
+            </div>
+            <div class="type" v-if="item.type == '8'">
+              <div v-for="(as, img) in item.answer" :key="img">
+                <el-link :href="getUrl(as)" target="_blank">{{ as.name }}</el-link>
+              </div>
+            </div>
+          </el-descriptions-item>
+        </el-descriptions>
       </div>
-      <div class="button">
-        <el-button type="primary" @click="toSave()">保存</el-button>
+      <div v-if="dialog.type == '3'">
+        <el-descriptions :column="2" :size="size" border>
+          <el-descriptions-item label="参加决赛时间"> kooriookami </el-descriptions-item>
+          <el-descriptions-item label="操作">
+            <el-button type="primary" @click="toSign('0')">确认参加</el-button>
+            <el-button type="warning" @click="toSign('1')">调整时间</el-button>
+            <el-button type="danger" @click="toSign('2')">放弃参加</el-button>
+          </el-descriptions-item>
+        </el-descriptions>
       </div>
     </el-dialog>
   </div>
@@ -121,6 +174,11 @@ const checkbox = ref([])
 const form = ref({})
 const dialog = ref({ type: '1', show: false, title: '报名信息' })
 
+const is_look = ref(false)
+
+// 当前流程
+const active = ref(1)
+
 const search = async (query = { skip, limit }) => {
   skip = query.skip
   limit = query.limit
@@ -135,6 +193,17 @@ const search = async (query = { skip, limit }) => {
     total.value = res.total
   }
 }
+// 查看
+const toView = (data) => {
+  is_look.value = true
+  form.value = data
+  investigate.value = data.info
+  for (const val of data.info) {
+    if (val.type == '5') file.value = val.reply
+    if (val.type == '1') checkbox.value = val.reply
+  }
+  dialog.value = { type: '2', show: true, title: '报名信息' }
+}
 // 修改
 const toEdit = (data) => {
   form.value = data
@@ -159,7 +228,10 @@ const sizeChange = (limits) => {
   search({ skip: 0, limit: limit })
 }
 const toClose = async () => {
+  is_look.value = false
   form.value = {}
+  file.value = []
+  checkbox.value = []
   investigate.value = []
   dialog.value = { show: false }
   await search({ skip, limit })
@@ -218,6 +290,38 @@ const toSave = async () => {
     toClose()
   }
 }
+// 决赛时间确认
+const toFinals = (data) => {
+  form.value = data
+  dialog.value = { type: '3', show: true, title: '决赛时间确认' }
+}
+// 时间确认
+const toSign = (type) => {
+  let title
+  if (type == '0') {
+    // 确认参加
+    title = '此操作将确认参加该决赛, 是否继续?'
+  } else if (type == '1') {
+    // 调整时间
+    title = '此操作将调整参加决赛的时间,由主办方与您沟通调整时间, 是否继续?'
+  } else {
+    // 放弃参加
+    title = '此操作将放弃参加该决赛, 是否继续?'
+  }
+  ElMessageBox.confirm(title, '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  })
+    .then(async () => {
+      ElMessage({
+        type: 'success',
+        message: '操作成功'
+      })
+      toClose()
+    })
+    .catch(() => {})
+}
 watch(
   user,
   async (item) => {
@@ -314,5 +418,12 @@ watch(
       background-color: #007aff;
     }
   }
+  :deep(.el-descriptions__body .el-descriptions__table.is-bordered .el-descriptions__cell) {
+    text-align: center;
+    width: 10px !important; /* 设置你想要的宽度 */
+  }
+  .status {
+    margin: 10px 0;
+  }
 }
 </style>

+ 3 - 3
src/views/center/parts/score.vue

@@ -9,7 +9,7 @@
             </el-steps>
           </el-col>
         </el-row>
-        <el-col :span="24" class="one">
+        <el-col :span="24" class="one" v-if="matchPathList.value && matchPathList.value.length > 0">
           <div class="one_left" @click="toAdd">添加分数</div>
         </el-col>
         <div class="table">
@@ -33,7 +33,7 @@
             <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
           </el-col>
         </div>
-        <div class="button">
+        <div class="button" v-if="matchPathList.value && matchPathList.value.length > 0">
           <el-button @click="back">上一步</el-button>
           <el-button @click="next">下一步</el-button>
         </div>
@@ -105,7 +105,7 @@ const loading = ref(false)
 onMounted(async () => {
   loading.value = true
   await searchOther()
-  await search({ skip, limit })
+  if (matchPathList.value && matchPathList.value.length > 0) await search({ skip, limit })
   loading.value = false
 })
 const searchOther = async () => {

+ 13 - 0
src/views/detail/matchDetail.vue

@@ -141,6 +141,16 @@
             </el-card>
           </div>
         </div>
+        <div class="info_3" v-if="info.form == '4'">
+          <div class="title">初赛结果公示</div>
+          <div class="content" style="margin: 20px 0 0 0">
+            <el-table :data="preliminaryList" stripe style="width: 100%">
+              <el-table-column align="center" prop="name" label="姓名" />
+              <el-table-column align="center" prop="project" label="项目名称" />
+              <el-table-column align="center" prop="time" label="时间" />
+            </el-table>
+          </div>
+        </div>
       </div>
     </el-col>
   </custom-layout>
@@ -193,6 +203,9 @@ const signTypeList = ref([])
 const ruleFormRef = ref()
 const form = ref({})
 
+// 初审公示
+const preliminaryList = ref([])
+
 const validatePhoneNumber = (rule, value, callback) => {
   const reg = /^1[3-9]\d{9}$/
   if (!value) {

+ 36 - 13
src/views/detail/preliminary.vue

@@ -71,17 +71,21 @@
         </div>
         <div class="type" v-if="item.type == '3'">
           <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <el-input size="large" v-model="item.reply" :placeholder="getField(item.problem)" />
+          <el-input size="large" v-model="item.reply" type="number" :placeholder="getField(item.problem)" />
         </div>
         <div class="type" v-if="item.type == '4'">
           <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <el-input v-model="item.reply" type="textarea" :placeholder="getField(item.problem)" />
+          <el-input size="large" v-model="item.reply" :placeholder="getField(item.problem)" />
         </div>
         <div class="type" v-if="item.type == '5'">
           <div class="remark" v-if="item.remark">{{ item.remark }}</div>
-          <custom-upload model="reply" :list="file" :limit="1" url="/files/web/cxyy_match/upload" @change="onUpload($event, item)"></custom-upload>
+          <el-input v-model="item.reply" type="textarea" :placeholder="getField(item.problem)" />
         </div>
         <div class="type" v-if="item.type == '6'">
+          <div class="remark" v-if="item.remark">{{ item.remark }}</div>
+          <custom-upload model="reply" :list="file" accept="*" :limit="10" url="/files/web/cxyy_match/upload" @change="onUpload($event, item)"></custom-upload>
+        </div>
+        <div class="type" v-if="item.type == '7'">
           <div class="list">
             <div v-for="(aa, ina) in item.answer" :key="ina" class="name">{{ aa.text }}</div>
           </div>
@@ -93,7 +97,7 @@
           </div>
           <div class="add" @click="toAdd(item)">+新增一行</div>
         </div>
-        <div class="type" v-if="item.type == '7'">
+        <div class="type" v-if="item.type == '8'">
           <div v-for="(as, img) in item.answer" :key="img">
             <el-link :href="getUrl(as)" target="_blank">{{ as.name }}</el-link>
           </div>
@@ -111,7 +115,6 @@
 <script setup>
 import moment from 'moment'
 import { get } from 'lodash-es'
-const $checkRes = inject('$checkRes')
 // 接口
 import { MatchStore } from '@/store/api/platform/match'
 const store = MatchStore()
@@ -228,14 +231,34 @@ const checkChange = (data, item) => {
 }
 const toSave = async () => {
   const data = { match_id: info.value.id, info: investigate.value }
-  if (user.value.id) data.user_id = user.value.id
-  else {
-    form.value.nick_name = form.value.account
-    data.user = form.value
-  }
-  const res = await matchRegStore.create(data)
-  if ($checkRes(res, true)) {
-    toBack()
+  if (user.value.id) {
+    data.user_id = user.value.id
+    const res = await matchRegStore.create(data)
+    if (res.errcode == '0') {
+      ElMessageBox.alert('请在 个人中心-活动管理-大赛报名 中查看报名信息', '报名信息', {
+        confirmButtonText: '确定',
+        callback: () => {
+          toBack()
+        }
+      })
+    } else ElMessage({ message: res.errmsg, type: 'error' })
+  } else {
+    if (!ruleFormRef.value) return
+    await ruleFormRef.value.validate(async (valid) => {
+      if (valid) {
+        form.value.nick_name = form.value.account
+        data.user = form.value
+        const res = await matchRegStore.create(data)
+        if (res.errcode == '0') {
+          ElMessageBox.alert('请在 个人中心-活动管理-大赛报名 中查看报名信息', '报名信息', {
+            confirmButtonText: '确定',
+            callback: () => {
+              toBack()
+            }
+          })
+        } else ElMessage({ message: res.errmsg, type: 'error' })
+      }
+    })
   }
 }
 // 返回上一页

+ 529 - 0
src/views/two/add/match copy.vue

@@ -0,0 +1,529 @@
+<template>
+  <div class="index">
+    <el-row>
+      <el-col :span="24" class="main" v-loading="loading">
+        <el-tabs v-model="activeName" type="card">
+          <el-tab-pane label="基本信息" name="first">
+            <custom-form v-model="form" :fields="oneformFields" :rules="rules" @save="toSave" @draftSave="toDraftSave">
+              <template #video>
+                <custom-upload model="video" :list="form.video" :limit="1" url="/files/web/cxyy_match/upload" @change="onUpload"></custom-upload>
+              </template>
+              <template #file>
+                <custom-upload model="file" :list="form.file" :limit="1" listType="picture-card" url="/files/web/cxyy_match/upload" @change="onUpload"></custom-upload>
+              </template>
+              <template #is_use>
+                <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+              </template>
+              <template #is_show>
+                <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+              </template>
+              <template #industry>
+                <el-option v-for="i in industryList" :key="i.id" :label="i.label" :value="i.value"></el-option>
+              </template>
+              <template #scale>
+                <el-radio v-for="i in scaleList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+              </template>
+              <template #match_type>
+                <el-radio v-for="i in matchTypeList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+              </template>
+              <template #type>
+                <el-option v-for="i in typeList" :key="i.id" :label="i.label" :value="i.value"></el-option>
+              </template>
+              <template #form>
+                <el-option v-for="i in formList" :key="i.id" :label="i.label" :value="i.value"></el-option>
+              </template>
+              <template #tags>
+                <el-select v-model="form.tags" multiple filterable allow-create default-first-option :reserve-keyword="false" placeholder="请选择标签" style="width: 100%">
+                  <el-option v-for="item in tagsList" :key="item.id" :label="item.title" :value="item.title" />
+                </el-select>
+              </template>
+            </custom-form>
+          </el-tab-pane>
+          <el-tab-pane label="拓展信息" name="second">
+            <custom-form v-model="form" :fields="twoformFields" :rules="{}" @save="toSave" @draftSave="toDraftSave">
+              <template #rules>
+                <div class="rules">
+                  <custom-form v-model="form.rules" :fields="rulesFields" :useSave="false">
+                    <template #rules1>
+                      <WangEditor v-model="form.rules.rules1" />
+                    </template>
+                    <template #rules2>
+                      <WangEditor v-model="form.rules.rules2" />
+                    </template>
+                    <template #rules3>
+                      <WangEditor v-model="form.rules.rules3" />
+                    </template>
+                    <template #rules4>
+                      <WangEditor v-model="form.rules.rules4" />
+                    </template>
+                    <template #rules5>
+                      <WangEditor v-model="form.rules.rules5" />
+                    </template>
+                    <template #rules6>
+                      <WangEditor v-model="form.rules.rules6" />
+                    </template>
+                    <template #rules7>
+                      <WangEditor v-model="form.rules.rules7" />
+                    </template>
+                    <template #rules8>
+                      <WangEditor v-model="form.rules.rules8" />
+                    </template>
+                    <template #rules9>
+                      <WangEditor v-model="form.rules.rules9" />
+                    </template>
+                    <template #rules10>
+                      <WangEditor v-model="form.rules.rules10" />
+                    </template>
+                    <template #rules11>
+                      <WangEditor v-model="form.rules.rules11" />
+                    </template>
+                    <template #rules12>
+                      <WangEditor v-model="form.rules.rules12" />
+                    </template>
+                  </custom-form>
+                </div>
+              </template>
+              <template #brief>
+                <WangEditor v-model="form.brief" />
+              </template>
+            </custom-form>
+          </el-tab-pane>
+          <el-tab-pane label="流程信息" name="third">
+            <custom-form v-model="form" :fields="thrformFields" :rules="{}" @save="toSave" @draftSave="toDraftSave">
+              <template #process>
+                <el-col :span="24" class="tables">
+                  <el-col :span="24" class="tables_1">
+                    <el-button type="primary" @click="addProcess()">添加</el-button>
+                  </el-col>
+                  <el-col :span="24">
+                    <el-table :data="processList" border>
+                      <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
+                      <el-table-column prop="name" label="流程名称" align="center">
+                        <template #default="scope">
+                          <el-input v-model="scope.row.name" placeholder="请输入流程名称" />
+                        </template>
+                      </el-table-column>
+                      <el-table-column prop="order_num" label="排序" align="center">
+                        <template #default="scope">
+                          <el-input v-model="scope.row.order_num" type="number" placeholder="请输入排序" />
+                        </template>
+                      </el-table-column>
+                      <el-table-column prop="is_use" label="是否启用" align="center">
+                        <template #default="scope">
+                          <el-select v-model="scope.row.is_use" placeholder="请选择是否启用">
+                            <el-option v-for="item in isUseList" :key="item.value" :label="item.label" :value="item.value" />
+                          </el-select>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="操作" align="center" width="100">
+                        <template #default="scope">
+                          <el-button type="danger" @click="delProcess(scope.row)">删除</el-button>
+                        </template>
+                      </el-table-column>
+                    </el-table>
+                  </el-col>
+                </el-col>
+              </template>
+            </custom-form>
+          </el-tab-pane>
+          <el-tab-pane label="报名信息设置" name="fourth" v-if="form.form == '4'">
+            <custom-form v-model="form" :fields="fourFields" :rules="rules" @save="toSave" @draftSave="toDraftSave">
+              <template #ext_info>
+                <el-col :span="24" class="add">
+                  <el-button type="primary" @click="addInvest()">添加</el-button>
+                </el-col>
+                <el-table :data="investigateList" border>
+                  <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
+                  <el-table-column prop="problem" label="字段名称" align="center"> </el-table-column>
+                  <el-table-column label="操作" align="center" width="200">
+                    <template #default="scope">
+                      <el-button type="primary" @click="updateInvest(scope.row)">修改</el-button>
+                      <el-button size="mini" type="danger" @click="delInvest(scope.row)">删除</el-button>
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </template>
+            </custom-form>
+          </el-tab-pane>
+          <el-tab-pane label="分数纬度设置" name="fifth" v-if="form.form == '4'">
+            <custom-form v-model="form" :fields="fifthformFields" :rules="{}" @save="toSave" @draftSave="toDraftSave">
+              <template #ext_finals>
+                <el-col :span="24" class="tables">
+                  <el-col :span="24" class="tables_1">
+                    <el-button type="primary" @click="addFinals()">添加</el-button>
+                  </el-col>
+                  <el-col :span="24">
+                    <el-table :data="finalsList" border>
+                      <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
+                      <el-table-column prop="name" label="纬度名称" align="center">
+                        <template #default="scope">
+                          <el-input v-model="scope.row.name" placeholder="请输入纬度名称" />
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="操作" align="center" width="100">
+                        <template #default="scope">
+                          <el-button type="danger" @click="delFinals(scope.row)">删除</el-button>
+                        </template>
+                      </el-table-column>
+                    </el-table>
+                  </el-col>
+                </el-col>
+              </template>
+            </custom-form>
+          </el-tab-pane>
+        </el-tabs>
+      </el-col>
+    </el-row>
+    <el-dialog v-model="dialogVisible" title="报名信息设置填写" width="800" :destroy-on-close="false" @close="toClose">
+      <custom-form v-model="investigateForm" :fields="fourformFields" :rules="fourRules" @save="toInvestigateSave" submitText="保存" :DraftSave="false">
+        <template #type>
+          <el-option v-for="i in proTypeList" :key="i.value" :label="i.label" :value="i.value"></el-option>
+        </template>
+        <template #answer>
+          <div class="answer" v-if="investigateForm.type == '0' || investigateForm.type == '1' || investigateForm.type == '2' || investigateForm.type == '7'">
+            <el-col :span="24" class="add">
+              <el-button type="primary" @click="addAnswer()">添加</el-button>
+            </el-col>
+            <el-table :data="answerList" border>
+              <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
+              <el-table-column prop="text" label="答案" align="center" width="500">
+                <template #default="scope">
+                  <el-input v-model="scope.row.text" placeholder="请输入答案" />
+                </template>
+              </el-table-column>
+              <el-table-column label="操作" align="center" width="100">
+                <template #default="scope">
+                  <el-button type="danger" @click="delAnswer(scope.row)">删除</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </div>
+          <div class="answer" v-if="investigateForm.type == '8'">
+            <custom-upload model="file" :list="answerFile" accept="*" :limit="10" url="/files/web/cxyy_match/upload" @change="onaUpload"></custom-upload>
+          </div>
+        </template>
+        <template #is_must>
+          <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+        </template>
+      </custom-form>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+// 组件
+import moment from 'moment'
+import { cloneDeep, get } from 'lodash-es'
+const $checkRes = inject('$checkRes')
+import { UserStore } from '@/store/user'
+const userStore = UserStore()
+const user = computed(() => userStore.user)
+// 接口
+import { MatchStore } from '@/store/api/platform/match'
+import { ProcessStore } from '@/store/api/platform/process'
+import { DictDataStore } from '@/store/api/system/dictData'
+import { TagsStore } from '@/store/api/system/tags'
+const store = MatchStore()
+const dictDataStore = DictDataStore()
+const tagsStore = TagsStore()
+const processStore = ProcessStore()
+// 加载中
+const loading = ref(false)
+const match_id = ref('')
+// 字典表
+const isUseList = ref([])
+const statusList = ref([])
+const typeList = ref([])
+const matchList = ref([])
+const formList = ref([])
+const tagsList = ref([])
+const industryList = ref([])
+const matchTypeList = ref([])
+const scaleList = ref([])
+// 流程列表
+const processList = ref([])
+const activeName = ref('first')
+const form = ref({ time: [], rules: {} })
+const oneformFields = ref([
+  { label: '封面', model: 'file', custom: true },
+  { label: '赛事名称', model: 'name' },
+  { label: '类别', model: 'form', type: 'select' },
+  { label: '标签', model: 'tags', custom: true },
+  { label: '类型', model: 'type', type: 'select' },
+  { label: '赛事规模', model: 'scale', type: 'radio' },
+  { label: '赛事类型', model: 'match_type', type: 'radio' },
+  { label: '路由', model: 'href', display: () => form.value.match_type == '1' },
+  { label: '组织单位', model: 'work' },
+  { label: '行业', model: 'industry', type: 'select' },
+  { label: '奖金(万元)', model: 'money' },
+  { label: '有效期', model: 'time', type: 'datetimerange' },
+  { label: '是否启用', model: 'is_use', type: 'radio' },
+  { label: '是否公开路演人信息', model: 'is_show', type: 'radio' },
+  { label: '视频', model: 'video', custom: true },
+  { label: '地址', model: 'address', type: 'textarea' },
+  { label: '备注', model: 'remark', type: 'textarea', display: () => form.value.form == '3' }
+])
+const twoformFields = ref([
+  { model: 'rules', custom: true },
+  { label: '简介', model: 'brief', custom: true }
+])
+const thrformFields = ref([{ label: '赛事流程', model: 'process', custom: true }])
+const fifthformFields = ref([{ label: '分数纬度', model: 'ext_finals', custom: true }])
+const fourFields = ref([{ label: '报名信息', model: 'ext_info', custom: true }])
+// 分数纬度列表
+const finalsList = ref([])
+// 赛事规则
+const rulesFields = ref([
+  { label: '大赛背景', model: 'rules1', custom: true },
+  { label: '大赛主题和目标', model: 'rules2', custom: true },
+  { label: '大赛基本情况介绍', model: 'rules3', custom: true },
+  { label: '赛题任务', model: 'rules4', custom: true },
+  { label: '赛程安排', model: 'rules5', custom: true },
+  { label: '赛制阶段', model: 'rules6', custom: true },
+  { label: '参赛资格', model: 'rules7', custom: true },
+  { label: '参赛报名', model: 'rules8', custom: true },
+  { label: '奖项设置与奖励办法', model: 'rules9', custom: true },
+  { label: '组织单位', model: 'rules10', custom: true },
+  { label: '赛事联络', model: 'rules11', custom: true },
+  { label: '赛事交流', model: 'rules12', custom: true }
+])
+const rules = reactive({
+  name: [{ required: true, message: '请输入赛事名称', trigger: 'blur' }],
+  form: [{ required: true, message: '请选择类别', trigger: 'blur' }],
+  scale: [{ required: true, message: '请选择赛事规模', trigger: 'blur' }],
+  match_type: [{ required: true, message: '请选择赛事类型', trigger: 'blur' }],
+  work: [{ required: true, message: '请输入组织单位', trigger: 'blur' }]
+})
+// 调查问卷
+const investigateList = ref([])
+const investigateForm = ref({})
+const fourformFields = ref([
+  { label: '字段名称', model: 'problem' },
+  { label: '类型', model: 'type', type: 'select' },
+  {
+    label: '答案',
+    model: 'answer',
+    custom: true,
+    display: () => investigateForm.value.type == '0' || investigateForm.value.type == '1' || investigateForm.value.type == '2' || investigateForm.value.type == '7' || investigateForm.value.type == '8'
+  },
+  { label: '是否必填', model: 'is_must', type: 'radio', display: () => investigateForm.value.type != '7' },
+  { label: '备注', model: 'remark', type: 'textarea' }
+])
+const fourRules = reactive({
+  problem: [{ required: true, message: '请输入字段名称', trigger: 'blur' }]
+})
+const dialogVisible = ref(false)
+const proTypeList = ref([
+  { value: '0', label: '单选' },
+  { value: '1', label: '多选' },
+  { value: '2', label: '下拉' },
+  { value: '3', label: '数值类型' },
+  { value: '4', label: '单行文本' },
+  { value: '5', label: '多行文本' },
+  { value: '6', label: '图片/文件' },
+  { value: '7', label: '数组' },
+  { value: '8', label: '附件模板' }
+])
+// 答案
+const answerList = ref([])
+const answerFile = ref([])
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  loading.value = false
+})
+const searchOther = async () => {
+  let result
+  // 是否使用
+  result = await dictDataStore.query({ code: 'isUse', is_use: '0' })
+  if ($checkRes(result)) isUseList.value = result.data
+  // 类型
+  result = await dictDataStore.query({ code: 'matchType', is_use: '0' })
+  if ($checkRes(result)) typeList.value = result.data
+  // 赛事类型
+  result = await dictDataStore.query({ code: 'activeType', is_use: '0' })
+  if ($checkRes(result)) matchTypeList.value = result.data
+  // 类别
+  result = await dictDataStore.query({ code: 'matchForm', is_use: '0' })
+  if ($checkRes(result)) formList.value = result.data
+  // 状态
+  result = await dictDataStore.query({ code: 'examStatus', is_use: '0' })
+  if ($checkRes(result)) statusList.value = result.data
+  // 赛事状态
+  result = await dictDataStore.query({ code: 'matchStatus', is_use: '0' })
+  if ($checkRes(result)) matchList.value = result.data
+  // 赛事规模
+  result = await dictDataStore.query({ code: 'matchScale', is_use: '0' })
+  if ($checkRes(result)) scaleList.value = result.data
+  // 标签
+  result = await tagsStore.query({ is_use: '0' })
+  if ($checkRes(result)) tagsList.value = result.data
+  // 行业
+  result = await dictDataStore.query({ code: 'matchIndustry', is_use: '0' })
+  if ($checkRes(result)) industryList.value = result.data
+}
+const toSave = async () => {
+  const data = cloneDeep(form.value)
+  const other = { status: '0', user: user.value.id }
+  if (data.time && data.time.length > 1) {
+    data.start_time = data.time[0]
+    data.end_time = data.time[1]
+  }
+  delete data.time
+  if (investigateList.value && investigateList.value.length > 0) data.ext_info = investigateList.value
+  if (finalsList.value && finalsList.value.length > 0) data.ext_finals = finalsList.value
+  let res
+  if (get(data, 'id')) res = await store.update({ ...data, ...other })
+  else res = await store.create({ ...data, ...other })
+  if (res.errcode == 0) {
+    ElMessageBox.alert('赛事发布成功,请在中查看赛事发布信息', '赛事发布', {
+      confirmButtonText: '确定',
+      callback: async () => {
+        if (res.data && res.data.id) match_id.value = res.data.id
+        await toProcessSave()
+        form.value = { time: [], rules: {} }
+        processList.value = []
+        activeName.value = 'first'
+      }
+    })
+  }
+}
+const toDraftSave = async () => {
+  const data = cloneDeep(form.value)
+  const other = { status: '-2', user: user.value.id }
+  if (data.time && data.time.length > 1) {
+    data.start_time = data.time[0]
+    data.end_time = data.time[1]
+  }
+  delete data.time
+  if (investigateList.value && investigateList.value.length > 0) data.ext_info = investigateList.value
+  if (finalsList.value && finalsList.value.length > 0) data.ext_finals = finalsList.value
+  let res
+  if (get(data, 'id')) res = await store.update({ ...data, ...other })
+  else res = await store.create({ ...data, ...other })
+  if (res.errcode == 0) {
+    ElMessageBox.alert('赛事发布成功,请在历史发布中选择赛事管理查看发布赛事信息', '赛事发布', {
+      confirmButtonText: '确定',
+      callback: async () => {
+        if (res.data && res.data.id) match_id.value = res.data.id
+        await toProcessSave()
+        form.value = { time: [], rules: {} }
+        processList.value = []
+        activeName.value = 'first'
+      }
+    })
+  }
+}
+// 上传图片
+const onUpload = (e) => {
+  const { model, value } = e
+  form.value[model] = value
+}
+// 上传图片
+const onaUpload = (e) => {
+  const { value } = e
+  answerFile.value = value
+}
+// 流程添加
+const toProcessSave = async () => {
+  for (const val of processList.value) {
+    const data = cloneDeep(val)
+    delete data.sid
+    if (!data.match) data.match = match_id.value
+    if (get(data, 'id')) await processStore.update(data)
+    else await processStore.create(data)
+  }
+}
+// 流程添加
+const addProcess = () => {
+  let list = processList.value || []
+  list.push({ sid: moment().valueOf(), name: '', time: '', is_use: '', match: form.value.id })
+  processList.value = list
+}
+// 流程删除
+const delProcess = async (e) => {
+  if (e.sid) {
+    let list = processList.value.filter((i) => i.sid != e.sid)
+    processList.value = list
+  } else {
+    let list = processList.value.filter((i) => i.id != e.id)
+    processList.value = list
+  }
+  if (e.id) await processStore.del(e.id)
+}
+
+// 维度添加
+const addFinals = () => {
+  let list = finalsList.value || []
+  list.push({ sid: moment().valueOf(), name: '' })
+  finalsList.value = list
+}
+// 维度删除
+const delFinals = async (e) => {
+  let list = finalsList.value.filter((i) => i.sid != e.sid)
+  finalsList.value = list
+}
+
+// 调查问卷填写
+const addInvest = () => {
+  dialogVisible.value = true
+  investigateForm.value = { sid: moment().valueOf(), problem: '', type: '', is_must: '', reply: '', answer: '', remark: '' }
+}
+// 删除调查问卷
+const delInvest = async (e) => {
+  let list = investigateList.value.filter((i) => i.sid != e.sid)
+  investigateList.value = list
+}
+// 保存
+const toInvestigateSave = (data) => {
+  if (answerList.value && answerList.value.length > 0) data.answer = answerList.value
+  else data.answer = answerFile.value
+  let investigate = investigateList.value.find((i) => i.sid == data.sid)
+  if (investigate) {
+    investigateList.value = investigateList.value.map((i) => {
+      if (i.sid == data.sid) return data
+      else return i
+    })
+  } else investigateList.value.push(data)
+  toClose()
+}
+const toClose = () => {
+  investigateForm.value = {}
+  answerList.value = []
+  dialogVisible.value = false
+}
+// 答案添加
+const addAnswer = () => {
+  let list = answerList.value || []
+  list.push({ sid: moment().valueOf(), text: '' })
+  answerList.value = list
+}
+//调查问卷修改
+const updateInvest = (e) => {
+  dialogVisible.value = true
+  if (e.answer && e.answer.length > 0) answerList.value = e.answer
+  investigateForm.value = e
+}
+//  答案删除
+const delAnswer = async (e) => {
+  let list = answerList.value.filter((i) => i.sid != e.sid)
+  answerList.value = list
+}
+</script>
+<style scoped lang="scss">
+.main {
+  .add {
+    margin: 0 0 10px 0;
+  }
+  .button {
+    text-align: center;
+    margin: 10px 0 0 0;
+  }
+  .tables {
+    .tables_1 {
+      margin: 0 0 10px 0;
+    }
+  }
+}
+</style>

+ 226 - 153
src/views/two/add/match.vue

@@ -2,46 +2,79 @@
   <div class="index">
     <el-row>
       <el-col :span="24" class="main" v-loading="loading">
-        <el-tabs v-model="activeName" type="card">
-          <el-tab-pane label="基本信息" name="first">
-            <custom-form v-model="form" :fields="oneformFields" :rules="rules" @save="toSave" @draftSave="toDraftSave">
-              <template #video>
-                <custom-upload model="video" :list="form.video" :limit="1" url="/files/web/cxyy_match/upload" @change="onUpload"></custom-upload>
-              </template>
-              <template #file>
+        <el-form ref="formRef" :model="form" :rules="rules" label-width="auto">
+          <el-tabs v-model="activeName" type="card">
+            <el-tab-pane label="基本信息" name="first">
+              <el-form-item label="封面" prop="file">
                 <custom-upload model="file" :list="form.file" :limit="1" listType="picture-card" url="/files/web/cxyy_match/upload" @change="onUpload"></custom-upload>
-              </template>
-              <template #is_use>
-                <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-              </template>
-              <template #is_show>
-                <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-              </template>
-              <template #industry>
-                <el-option v-for="i in industryList" :key="i.id" :label="i.label" :value="i.value"></el-option>
-              </template>
-              <template #scale>
-                <el-radio v-for="i in scaleList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-              </template>
-              <template #match_type>
-                <el-radio v-for="i in matchTypeList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-              </template>
-              <template #type>
-                <el-option v-for="i in typeList" :key="i.id" :label="i.label" :value="i.value"></el-option>
-              </template>
-              <template #form>
-                <el-option v-for="i in formList" :key="i.id" :label="i.label" :value="i.value"></el-option>
-              </template>
-              <template #tags>
-                <el-select v-model="form.tags" multiple filterable allow-create default-first-option :reserve-keyword="false" placeholder="请选择标签" style="width: 100%">
+              </el-form-item>
+              <el-form-item label="赛事名称" prop="name">
+                <el-input size="large" v-model="form.name" placeholder="请输入赛事名称" />
+              </el-form-item>
+              <el-form-item label="类别" prop="form">
+                <el-select v-model="form.form" placeholder="请选择类别" size="large" style="width: 100%">
+                  <el-option v-for="item in formList" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </el-form-item>
+              <el-form-item label="标签" prop="tags">
+                <el-select size="large" v-model="form.tags" multiple filterable allow-create default-first-option :reserve-keyword="false" placeholder="请选择标签" style="width: 100%">
                   <el-option v-for="item in tagsList" :key="item.id" :label="item.title" :value="item.title" />
                 </el-select>
-              </template>
-            </custom-form>
-          </el-tab-pane>
-          <el-tab-pane label="拓展信息" name="second">
-            <custom-form v-model="form" :fields="twoformFields" :rules="{}" @save="toSave" @draftSave="toDraftSave">
-              <template #rules>
+              </el-form-item>
+              <el-form-item label="类型" prop="type">
+                <el-select v-model="form.type" placeholder="请选择类型" size="large" style="width: 100%">
+                  <el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </el-form-item>
+              <el-form-item label="赛事规模" prop="scale">
+                <el-radio-group v-model="form.scale">
+                  <el-radio v-for="item in scaleList" :key="item.value" :value="item.value" size="large">{{ item.label }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+              <el-form-item label="赛事类型" prop="match_type">
+                <el-radio-group v-model="form.match_type">
+                  <el-radio v-for="item in matchTypeList" :key="item.value" :value="item.value" size="large">{{ item.label }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+              <el-form-item label="路由" prop="href" v-if="form.match_type == '1'">
+                <el-input size="large" v-model="form.href" placeholder="请输入路由" />
+              </el-form-item>
+              <el-form-item label="组织单位" prop="work">
+                <el-input size="large" v-model="form.work" placeholder="请输入组织单位" />
+              </el-form-item>
+              <el-form-item label="行业" prop="industry">
+                <el-select v-model="form.type" placeholder="请选择行业" size="large" style="width: 100%">
+                  <el-option v-for="item in industryList" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </el-form-item>
+              <el-form-item label="奖金(万元)" prop="money">
+                <el-input size="large" v-model="form.money" placeholder="请输入奖金(万元)" />
+              </el-form-item>
+              <el-form-item label="有效期" prop="time">
+                <el-date-picker v-model="form.time" type="datetimerange" start-placeholder="开始日期" end-placeholder="结束日期" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"> </el-date-picker>
+              </el-form-item>
+              <el-form-item label="是否启用" prop="is_use">
+                <el-radio-group v-model="form.is_use">
+                  <el-radio v-for="item in isUseList" :key="item.value" :value="item.value" size="large">{{ item.label }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+              <el-form-item label="是否公开路演人信息" prop="is_show" v-if="form.form == '3'">
+                <el-radio-group v-model="form.is_show">
+                  <el-radio v-for="item in isUseList" :key="item.value" :value="item.value" size="large">{{ item.label }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+              <el-form-item label="视频" prop="vide">
+                <custom-upload model="video" :list="form.video" :limit="1" url="/files/web/cxyy_match/upload" @change="onUpload"></custom-upload>
+              </el-form-item>
+              <el-form-item label="地址" prop="address">
+                <el-input size="large" v-model="form.address" type="textarea" placeholder="请输入地址" />
+              </el-form-item>
+              <el-form-item label="备注" prop="remark">
+                <el-input size="large" v-model="form.remark" type="textarea" placeholder="请输入备注" />
+              </el-form-item>
+            </el-tab-pane>
+            <el-tab-pane label="拓展信息" name="second">
+              <el-form-item label="" prop="file">
                 <div class="rules">
                   <custom-form v-model="form.rules" :fields="rulesFields" :useSave="false">
                     <template #rules1>
@@ -82,15 +115,13 @@
                     </template>
                   </custom-form>
                 </div>
-              </template>
-              <template #brief>
+              </el-form-item>
+              <el-form-item label="简介" prop="brief">
                 <WangEditor v-model="form.brief" />
-              </template>
-            </custom-form>
-          </el-tab-pane>
-          <el-tab-pane label="流程信息" name="third">
-            <custom-form v-model="form" :fields="thrformFields" :rules="{}" @save="toSave" @draftSave="toDraftSave">
-              <template #process>
+              </el-form-item>
+            </el-tab-pane>
+            <el-tab-pane label="流程信息" name="third">
+              <el-form-item label="" prop="process">
                 <el-col :span="24" class="tables">
                   <el-col :span="24" class="tables_1">
                     <el-button type="primary" @click="addProcess()">添加</el-button>
@@ -123,29 +154,55 @@
                     </el-table>
                   </el-col>
                 </el-col>
-              </template>
-            </custom-form>
-          </el-tab-pane>
-          <el-tab-pane label="报名信息设置" name="fourth" v-if="form.form == '4'">
-            <el-col :span="24" class="add">
-              <el-button type="primary" @click="addInvest()">添加</el-button>
-            </el-col>
-            <el-table :data="investigateList" border>
-              <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
-              <el-table-column prop="problem" label="问题" align="center"> </el-table-column>
-              <el-table-column label="操作" align="center" width="200">
-                <template #default="scope">
-                  <el-button type="primary" @click="updateInvest(scope.row)">修改</el-button>
-                  <el-button size="mini" type="danger" @click="delInvest(scope.row)">删除</el-button>
-                </template>
-              </el-table-column>
-            </el-table>
-            <div class="button">
-              <el-button type="warning" @click="InvestSave('-2')">保存草稿</el-button>
-              <el-button type="primary" @click="InvestSave('0')">保存并提交审核</el-button>
-            </div>
-          </el-tab-pane>
-        </el-tabs>
+              </el-form-item>
+            </el-tab-pane>
+            <el-tab-pane label="报名信息设置" name="fourth" v-if="form.form == '4'">
+              <el-form-item label="" prop="ext_info">
+                <el-col :span="24" class="add">
+                  <el-button type="primary" @click="addInvest()">添加</el-button>
+                </el-col>
+                <el-table :data="investigateList" border>
+                  <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
+                  <el-table-column prop="problem" label="字段名称" align="center"> </el-table-column>
+                  <el-table-column label="操作" align="center" width="200">
+                    <template #default="scope">
+                      <el-button type="primary" @click="updateInvest(scope.row)">修改</el-button>
+                      <el-button size="mini" type="danger" @click="delInvest(scope.row)">删除</el-button>
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </el-form-item>
+            </el-tab-pane>
+            <el-tab-pane label="分数纬度设置" name="fifth" v-if="form.form == '4'">
+              <el-form-item label="" prop="ext_finals">
+                <el-col :span="24" class="tables">
+                  <el-col :span="24" class="tables_1">
+                    <el-button type="primary" @click="addFinals()">添加</el-button>
+                  </el-col>
+                  <el-col :span="24">
+                    <el-table :data="finalsList" border>
+                      <el-table-column type="index" label="序号" width="80" align="center"> </el-table-column>
+                      <el-table-column prop="name" label="纬度名称" align="center">
+                        <template #default="scope">
+                          <el-input v-model="scope.row.name" placeholder="请输入纬度名称" />
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="操作" align="center" width="100">
+                        <template #default="scope">
+                          <el-button type="danger" @click="delFinals(scope.row)">删除</el-button>
+                        </template>
+                      </el-table-column>
+                    </el-table>
+                  </el-col>
+                </el-col>
+              </el-form-item>
+            </el-tab-pane>
+          </el-tabs>
+          <el-col :span="24" class="button">
+            <el-button type="warning" size="large" @click="toDraftSave(formRef)">保存草稿</el-button>
+            <el-button type="primary" size="large" @click="toSave(formRef)">保存并提交审核</el-button>
+          </el-col>
+        </el-form>
       </el-col>
     </el-row>
     <el-dialog v-model="dialogVisible" title="报名信息设置填写" width="800" :destroy-on-close="false" @close="toClose">
@@ -154,7 +211,7 @@
           <el-option v-for="i in proTypeList" :key="i.value" :label="i.label" :value="i.value"></el-option>
         </template>
         <template #answer>
-          <div class="answer" v-if="investigateForm.type == '0' || investigateForm.type == '1' || investigateForm.type == '2' || investigateForm.type == '6'">
+          <div class="answer" v-if="investigateForm.type == '0' || investigateForm.type == '1' || investigateForm.type == '2' || investigateForm.type == '7'">
             <el-col :span="24" class="add">
               <el-button type="primary" @click="addAnswer()">添加</el-button>
             </el-col>
@@ -172,8 +229,8 @@
               </el-table-column>
             </el-table>
           </div>
-          <div class="answer" v-if="investigateForm.type == '7'">
-            <custom-upload model="file" :list="answerFile" :limit="1" url="/files/web/cxyy_match/upload" @change="onaUpload"></custom-upload>
+          <div class="answer" v-if="investigateForm.type == '8'">
+            <custom-upload model="file" :list="answerFile" accept="*" :limit="10" url="/files/web/cxyy_match/upload" @change="onaUpload"></custom-upload>
           </div>
         </template>
         <template #is_must>
@@ -217,31 +274,11 @@ const scaleList = ref([])
 // 流程列表
 const processList = ref([])
 const activeName = ref('first')
-const form = ref({ time: [], rules: {} })
-const oneformFields = ref([
-  { label: '封面', model: 'file', custom: true },
-  { label: '赛事名称', model: 'name' },
-  { label: '类别', model: 'form', type: 'select' },
-  { label: '标签', model: 'tags', custom: true },
-  { label: '类型', model: 'type', type: 'select' },
-  { label: '赛事规模', model: 'scale', type: 'radio' },
-  { label: '赛事类型', model: 'match_type', type: 'radio' },
-  { label: '路由', model: 'href', display: () => form.value.match_type == '1' },
-  { label: '组织单位', model: 'work' },
-  { label: '行业', model: 'industry', type: 'select' },
-  { label: '奖金(万元)', model: 'money' },
-  { label: '有效期', model: 'time', type: 'datetimerange' },
-  { label: '是否启用', model: 'is_use', type: 'radio' },
-  { label: '是否公开路演人信息', model: 'is_show', type: 'radio' },
-  { label: '视频', model: 'video', custom: true },
-  { label: '地址', model: 'address', type: 'textarea' },
-  { label: '备注', model: 'remark', type: 'textarea', display: () => form.value.form == '3' }
-])
-const twoformFields = ref([
-  { model: 'rules', custom: true },
-  { label: '简介', model: 'brief', custom: true }
-])
-const thrformFields = ref([{ label: '赛事流程', model: 'process', custom: true }])
+// 表单
+const formRef = ref()
+const form = ref({ video: [], time: [], rules: {} })
+// 分数纬度列表
+const finalsList = ref([])
 // 赛事规则
 const rulesFields = ref([
   { label: '大赛背景', model: 'rules1', custom: true },
@@ -268,30 +305,31 @@ const rules = reactive({
 const investigateList = ref([])
 const investigateForm = ref({})
 const fourformFields = ref([
-  { label: '问题', model: 'problem' },
+  { label: '字段名称', model: 'problem' },
   { label: '类型', model: 'type', type: 'select' },
   {
     label: '答案',
     model: 'answer',
     custom: true,
-    display: () => investigateForm.value.type == '0' || investigateForm.value.type == '1' || investigateForm.value.type == '2' || investigateForm.value.type == '6' || investigateForm.value.type == '7'
+    display: () => investigateForm.value.type == '0' || investigateForm.value.type == '1' || investigateForm.value.type == '2' || investigateForm.value.type == '7' || investigateForm.value.type == '8'
   },
-  { label: '是否必填', model: 'is_must', type: 'radio' },
+  { label: '是否必填', model: 'is_must', type: 'radio', display: () => investigateForm.value.type != '7' },
   { label: '备注', model: 'remark', type: 'textarea' }
 ])
 const fourRules = reactive({
-  problem: [{ required: true, message: '请输入问题', trigger: 'blur' }]
+  problem: [{ required: true, message: '请输入字段名称', trigger: 'blur' }]
 })
 const dialogVisible = ref(false)
 const proTypeList = ref([
   { value: '0', label: '单选' },
   { value: '1', label: '多选' },
   { value: '2', label: '下拉' },
-  { value: '3', label: '单行文本' },
-  { value: '4', label: '多行文本' },
-  { value: '5', label: '图片/文件' },
-  { value: '6', label: '数组' },
-  { value: '7', label: '附件模板' }
+  { value: '3', label: '数值类型' },
+  { value: '4', label: '单行文本' },
+  { value: '5', label: '多行文本' },
+  { value: '6', label: '图片/文件' },
+  { value: '7', label: '数组' },
+  { value: '8', label: '附件模板' }
 ])
 // 答案
 const answerList = ref([])
@@ -332,43 +370,77 @@ const searchOther = async () => {
   result = await dictDataStore.query({ code: 'matchIndustry', is_use: '0' })
   if ($checkRes(result)) industryList.value = result.data
 }
-const toSave = async () => {
-  const data = cloneDeep(form.value)
-  const other = { status: '0', user: user.value.id }
-  if (data.time && data.time.length > 1) {
-    data.start_time = data.time[0]
-    data.end_time = data.time[1]
-  }
-  delete data.time
-  let res
-  if (get(data, 'id')) res = await store.update({ ...data, ...other })
-  else res = await store.create({ ...data, ...other })
-  if (res.errcode == 0) {
-    if (res.data && res.data.id) match_id.value = res.data.id
-    await toProcessSave()
-    ElMessage({ message: `发布成功可以上历史发布查看`, type: 'success' })
-    form.value = { time: [], rules: {} }
-    processList.value = []
-  }
+const toSave = async (formEl) => {
+  if (!formEl) return
+  await formEl.validate(async (valid) => {
+    if (valid) {
+      const data = cloneDeep(form.value)
+      const other = { status: '0', user: user.value.id }
+      if (data.time && data.time.length > 1) {
+        data.start_time = data.time[0]
+        data.end_time = data.time[1]
+      }
+      delete data.time
+      if (investigateList.value && investigateList.value.length > 0) data.ext_info = investigateList.value
+      if (finalsList.value && finalsList.value.length > 0) data.ext_finals = finalsList.value
+      let res
+      if (get(data, 'id')) res = await store.update({ ...data, ...other })
+      else res = await store.create({ ...data, ...other })
+      if (res.errcode == 0) {
+        ElMessageBox.alert('赛事发布成功,请在中查看赛事发布信息', '赛事发布', {
+          confirmButtonText: '确定',
+          callback: async () => {
+            if (res.data && res.data.id) match_id.value = res.data.id
+            await toProcessSave()
+            form.value = { time: [], rules: {} }
+            processList.value = []
+            activeName.value = 'first'
+          }
+        })
+      }
+    } else {
+      ElMessage({
+        message: '有相关必填项没有填写',
+        type: 'warning'
+      })
+    }
+  })
 }
-const toDraftSave = async () => {
-  const data = cloneDeep(form.value)
-  const other = { status: '-2', user: user.value.id }
-  if (data.time && data.time.length > 1) {
-    data.start_time = data.time[0]
-    data.end_time = data.time[1]
-  }
-  delete data.time
-  let res
-  if (get(data, 'id')) res = await store.update({ ...data, ...other })
-  else res = await store.create({ ...data, ...other })
-  if (res.errcode == 0) {
-    if (res.data && res.data.id) match_id.value = res.data.id
-    await toProcessSave()
-    ElMessage({ message: `发布成功可以上历史发布查看`, type: 'success' })
-    form.value = { time: [], rules: {} }
-    processList.value = []
-  }
+const toDraftSave = async (formEl) => {
+  if (!formEl) return
+  await formEl.validate(async (valid) => {
+    if (valid) {
+      const data = cloneDeep(form.value)
+      const other = { status: '-2', user: user.value.id }
+      if (data.time && data.time.length > 1) {
+        data.start_time = data.time[0]
+        data.end_time = data.time[1]
+      }
+      delete data.time
+      if (investigateList.value && investigateList.value.length > 0) data.ext_info = investigateList.value
+      if (finalsList.value && finalsList.value.length > 0) data.ext_finals = finalsList.value
+      let res
+      if (get(data, 'id')) res = await store.update({ ...data, ...other })
+      else res = await store.create({ ...data, ...other })
+      if (res.errcode == 0) {
+        ElMessageBox.alert('赛事发布成功,请在历史发布中选择赛事管理查看发布赛事信息', '赛事发布', {
+          confirmButtonText: '确定',
+          callback: async () => {
+            if (res.data && res.data.id) match_id.value = res.data.id
+            await toProcessSave()
+            form.value = { time: [], rules: {} }
+            processList.value = []
+            activeName.value = 'first'
+          }
+        })
+      }
+    } else {
+      ElMessage({
+        message: '有相关必填项没有填写',
+        type: 'warning'
+      })
+    }
+  })
 }
 // 上传图片
 const onUpload = (e) => {
@@ -407,6 +479,19 @@ const delProcess = async (e) => {
   }
   if (e.id) await processStore.del(e.id)
 }
+
+// 维度添加
+const addFinals = () => {
+  let list = finalsList.value || []
+  list.push({ sid: moment().valueOf(), name: '' })
+  finalsList.value = list
+}
+// 维度删除
+const delFinals = async (e) => {
+  let list = finalsList.value.filter((i) => i.sid != e.sid)
+  finalsList.value = list
+}
+
 // 调查问卷填写
 const addInvest = () => {
   dialogVisible.value = true
@@ -452,18 +537,6 @@ const delAnswer = async (e) => {
   let list = answerList.value.filter((i) => i.sid != e.sid)
   answerList.value = list
 }
-//  保存并提交审核
-const InvestSave = async (status) => {
-  const data = cloneDeep(form.value)
-  const other = { status, user: user.value.id }
-  let res
-  if (get(data, 'id')) res = await store.update({ id: data.id, ext_info: investigateList.value, ...other, ...data })
-  else res = await store.create({ ext_info: investigateList.value, ...other, ...data })
-  if (res.errcode == 0) {
-    ElMessage({ message: `发布成功可以上历史发布查看`, type: 'success' })
-    form.value = { time: [], rules: {} }
-  }
-}
 </script>
 <style scoped lang="scss">
 .main {

+ 116 - 0
src/views/two/add/news1.vue

@@ -0,0 +1,116 @@
+<template>
+  <div class="index">
+    <el-row>
+      <el-col :span="24" class="main" v-loading="loading">
+        <custom-form v-model="form" :fields="formFields" :rules="rules" @save="toSave" @draftSave="toDraftSave">
+          <template #logo>
+            <custom-upload model="logo" :list="form.logo" :limit="1" url="/files/web/cxyy_news/upload" @change="onUpload" listType="picture-card"></custom-upload>
+          </template>
+          <template #is_use>
+            <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+          </template>
+          <template #is_show>
+            <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+          </template>
+          <template #tags>
+            <el-select v-model="form.tags" multiple filterable allow-create default-first-option :reserve-keyword="false" placeholder="请选择标签" style="width: 100%">
+              <el-option v-for="item in tagsList" :key="item.id" :label="item.title" :value="item.title" />
+            </el-select>
+          </template>
+          <template #content>
+            <WangEditor v-model="form.content" />
+          </template>
+        </custom-form>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+import moment from 'moment'
+import { cloneDeep, get } from 'lodash-es'
+const $checkRes = inject('$checkRes')
+import { UserStore } from '@/store/user'
+const userStore = UserStore()
+const user = computed(() => userStore.user)
+// 接口
+import { NewsStore } from '@/store/api/platform/news'
+import { DictDataStore } from '@/store/api/system/dictData'
+import { TagsStore } from '@/store/api/system/tags'
+const store = NewsStore()
+const dictDataStore = DictDataStore()
+const tagsStore = TagsStore()
+// 加载中
+const loading = ref(false)
+
+// 字典表
+const isUseList = ref([])
+const statusList = ref([])
+const tagsList = ref([])
+
+const form = ref({ logo: [], type: '1' })
+const formFields = ref([
+  { label: '封面', model: 'logo', custom: true },
+  { label: '标题', model: 'title' },
+  { label: '标签', model: 'tags', custom: true },
+  { label: '发布人', model: 'person', options: { disabled: true } },
+  { label: '发布时间', model: 'time', type: 'date', options: { disabled: true } },
+  { label: '浏览量', model: 'number', options: { disabled: true } },
+  { label: '是否公开', model: 'is_use', type: 'radio' },
+  { label: '是否在首页显示', model: 'is_show', type: 'radio' },
+  { label: '内容', model: 'content', custom: true }
+])
+const rules = reactive({
+  logo: [{ required: true, message: '请上传封面', trigger: 'blur' }],
+  name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
+  content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
+})
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  form.value = { status: '0', logo: [], type: '1', user: user.value.id, time: moment().format('YYYY-MM-DD'), person: user.value.nick_name }
+  loading.value = false
+})
+const searchOther = async () => {
+  let result
+  // 是否使用
+  result = await dictDataStore.query({ code: 'isUse', is_use: '0' })
+  if ($checkRes(result)) isUseList.value = result.data
+  // 状态
+  result = await dictDataStore.query({ code: 'examStatus', is_use: '0' })
+  if ($checkRes(result)) statusList.value = result.data
+  // 标签
+  result = await tagsStore.query({ is_use: '0' })
+  if ($checkRes(result)) tagsList.value = result.data
+}
+const toSave = async () => {
+  const data = cloneDeep(form.value)
+  const other = { status: '0', type: '1', user: user.value.id, time: moment().format('YYYY-MM-DD'), person: user.value.nick_name }
+  let res
+  if (get(data, 'id')) res = await store.update({ ...data, ...other })
+  else res = await store.create({ ...data, ...other })
+  if (res.errcode == 0) {
+    ElMessage({ message: `发布成功可以上历史发布查看`, type: 'success' })
+    form.value = {}
+  }
+}
+const toDraftSave = async () => {
+  const data = cloneDeep(form.value)
+  const other = { status: '-2', type: '1', user: user.value.id, time: moment().format('YYYY-MM-DD'), person: user.value.nick_name }
+  let res
+  if (get(data, 'id')) res = await store.update({ ...data, ...other })
+  else res = await store.create({ ...data, ...other })
+  if (res.errcode == 0) {
+    ElMessage({ message: `发布成功可以上历史发布查看`, type: 'success' })
+    form.value = {}
+  }
+}
+
+// 上传图片
+const onUpload = (e) => {
+  const { model, value } = e
+  form.value[model] = value
+}
+</script>
+<style scoped lang="scss"></style>

+ 1 - 0
src/views/two/add/news2.vue

@@ -65,6 +65,7 @@ const rules = reactive({
 onMounted(async () => {
   loading.value = true
   await searchOther()
+  form.value = { status: '0', logo: [], type: '2', user: user.value.id, time: moment().format('YYYY-MM-DD'), person: user.value.nick_name }
   loading.value = false
 })
 const searchOther = async () => {

+ 7 - 3
src/views/two/index.vue

@@ -13,6 +13,7 @@
           <achievement v-if="value1 == 'achievement'"></achievement>
           <demand v-else-if="value1 == 'demand'"></demand>
           <news2 v-else-if="value1 == 'news2'"></news2>
+          <news1 v-else-if="value1 == 'news1'"></news1>
           <supply v-else-if="value1 == 'supply'"></supply>
           <footplate v-else-if="value1 == 'footplate'"></footplate>
           <match v-else-if="value1 == 'match'"></match>
@@ -28,6 +29,7 @@
           <achievement2 v-if="value2 == 'achievement'"></achievement2>
           <demand2 v-else-if="value2 == 'demand'"></demand2>
           <news22 v-else-if="value2 == 'news2'"></news22>
+          <news11 v-else-if="value2 == 'news11'"></news11>
           <supply2 v-else-if="value2 == 'supply'"></supply2>
           <footplate2 v-else-if="value2 == 'footplate'"></footplate2>
           <match2 v-else-if="value2 == 'match'"></match2>
@@ -44,6 +46,7 @@
 import achievement from './add/achievement.vue'
 import demand from './add/demand.vue'
 import news2 from './add/news2.vue'
+import news1 from './add/news1.vue'
 import supply from './add/supply.vue'
 import footplate from './add/footplate.vue'
 import match from './add/match.vue'
@@ -52,6 +55,7 @@ import project from './add/project.vue'
 import achievement2 from '../center/achievement.vue'
 import demand2 from '../center/demand.vue'
 import news22 from '../center/news2.vue'
+import news11 from '../center/news1.vue'
 import supply2 from '../center/supply.vue'
 import footplate2 from '../center/footplate.vue'
 import match2 from '../center/match.vue'
@@ -67,8 +71,8 @@ const options = [
   { id: 4, name: '发布成果', route_name: 'achievement', path: '/achievement', icon: 'Medal' },
   { id: 5, name: '发布需求', route_name: 'demand', path: '/demand', icon: 'DataBoard' },
   { id: 8, name: '行业动态', route_name: 'news2', path: '/news2', icon: 'Message' },
-  { id: 9, name: '发布供给', route_name: 'supply', path: '/supply', icon: 'Notification' },
-  // { id: 10, name: '发布中试', route_name: 'footplate', path: '/footplate', icon: 'TakeawayBox' },
+  { id: 9, name: '赛事通知', route_name: 'news1', path: '/news1', icon: 'Message' },
+  { id: 10, name: '发布供给', route_name: 'supply', path: '/supply', icon: 'Notification' },
   { id: 11, name: '发布赛事', route_name: 'match', path: '/match', icon: 'CollectionTag' },
   { id: 13, name: '发布项目', route_name: 'project', path: '/project', icon: 'Trophy' }
 ]
@@ -77,7 +81,7 @@ const options2 = [
   { id: 5, name: '需求管理', route_name: 'demand', path: '/demand', icon: 'DataBoard' },
   { id: 8, name: '行业动态', route_name: 'news2', path: '/news2', icon: 'Message' },
   { id: 9, name: '供给管理', route_name: 'supply', path: '/supply', icon: 'Notification' },
-  // { id: 10, name: '中试管理', route_name: 'footplate', path: '/footplate', icon: 'TakeawayBox' },
+  { id: 10, name: '赛事通知', route_name: 'news11', path: '/news1', icon: 'Message' },
   { id: 11, name: '赛事管理', route_name: 'match', path: '/match', icon: 'CollectionTag' },
   { id: 13, name: '项目管理', route_name: 'project', path: '/project', icon: 'Trophy' }
 ]