Browse Source

修改依托单位

zs 2 years ago
parent
commit
645256e2bc

+ 123 - 3
src/views/unit/applyflair/add.vue

@@ -1,11 +1,131 @@
 <template>
-  <div id="index">
+  <div id="add">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_back="true" @toBack="toBack"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="CForm" :fields="fields" :rules="rules" :form="form" @dataChange="dataChange" labelWidth="auto" @save="toSave">
+            <template #studio_id>
+              <el-option v-for="i in studioList" :key="i._id" :label="i.name" :value="i._id"></el-option>
+            </template>
+            <template #file>
+              <component :is="CFile" model="file" :limit="limit" :url="url" :list="form.file" @change="onChange"></component>
+            </template>
+          </component>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import store from '@/stores/counter';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CForm from '@/components/c-form.vue';
+import CFile from '@/components/c-upload.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, reactive } from 'vue';
+import type { FormRules } from 'element-plus';
+import { ElMessage } from 'element-plus';
+import { useRoute } from 'vue-router';
+// #region 接口
+import { ApplyflairStore } from '@common/src/stores/studio/studios/applyflair'; //申请保留资质
+import { StudioStore } from '@common/src/stores/studio/studios/studio'; // 工作室
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; //个人账号申请科学家工作室权限表
+import type { IQueryResult } from '@/util/types.util';
+const applyflair = ApplyflairStore();
+const studio = StudioStore();
+const unitStudioApply = UnitStudioApplyStore();
+let route = useRoute();
+// 必填项
+const rules = reactive<FormRules>({
+  studio_id: [{ required: true, message: '请选择工作室名称', trigger: 'change' }],
+  file: [{ required: true, message: '请上传评估文件', trigger: 'change' }],
+  apply_time: [{ required: true, message: '请选择申请时间', trigger: 'change' }],
+});
+// 表单
+let fields: Ref<any[]> = ref([
+  { label: '依托单位名称', model: 'company_name', options: { readonly: true } },
+  { label: '工作室名称', model: 'studio_id', type: 'select' },
+  { label: '评估文件', model: 'file', custom: true },
+  { label: '申请时间', model: 'apply_time', type: 'date' },
+]);
+let limit: Ref<number> = ref(1);
+let url: Ref<string> = ref('/files/studioadmin/applyflair/upload');
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String; company: string; phone: string }> = ref({ _id: '', status: '', company: '', phone: '' });
+// 表单
+let form: Ref<{ file: Array<[]>; studio_name: string }> = ref({ file: [], studio_name: '' });
+// 工作室列表
+let studioList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search();
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async () => {
+  let data = {
+    user_id: unitInfo.value._id,
+    company_name: unitInfo.value.company,
+    file: [],
+    studio_name: '',
+  };
+  if (route.query && route.query.id) {
+    let id = route.query.id;
+    const res: IQueryResult = await applyflair.fetch(id);
+    if (res.errcode == 0) {
+      if (res.data) form.value = res.data as { content: string; file: Array<[]>; studio_name: string };
+    }
+  } else {
+    form.value = { ...data };
+  }
+};
+// 返回
+const toBack = () => {
+  window.history.go(-1);
+};
+// 数据选择
+const dataChange = ({ model, value }) => {
+  if (model == 'studio_id') {
+    let data = studioList.value.find((i) => i.id == value);
+    if (data) form.value.studio_name = data.name;
+  }
+};
+// 上传
+const onChange = (e: { model: string; value: Array<[]> }) => {
+  const { model, value } = e;
+  form.value[model] = value;
+};
+// 添加
+const toSave = async (data: { _id: string }) => {
+  let res: IQueryResult;
+  if (data._id) res = await applyflair.update(data);
+  else res = await applyflair.create(data);
+  if (res.errcode == 0) {
+    ElMessage({ type: 'success', message: '维护信息成功' });
+    toBack();
+  } else ElMessage({ type: 'warning', message: `${res.errmsg}` });
+};
+// 查询其他信息
+const searchOther = async () => {
+  // 工作室
+  const p1: IQueryResult = await studio.query({ status: '7', user_id: user.value._id });
+  studioList.value = p1.data as [];
+};
+</script>
 
 <style scoped></style>

+ 153 - 4
src/views/unit/applyflair/index.vue

@@ -1,11 +1,160 @@
 <template>
   <div id="index">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_search="true" :fields="fields" @search="partSearch">
+            <template #status>
+              <el-option v-for="i in statusList" :key="i.dict_value" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+          </component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="Btn1" @toAdd="toAdd"></component>
+        </el-col>
+        <el-col :span="24" class="thr">
+          <component
+            :is="CTable"
+            :fields="fields"
+            :opera="opera"
+            :select="false"
+            :selected="selected"
+            @handleSelect="handleSelect"
+            @query="search"
+            :data="tableData"
+            :total="total"
+            @edit="toEdit"
+            @del="toDel"
+          >
+          </component>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
+<script setup lang="ts">
+import store from '@/stores/counter';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CTable from '@/components/c-table.vue';
+import Btn1 from '@/components/btn-1.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { ElMessage } from 'element-plus';
+import { useRouter } from 'vue-router';
+// #region 接口
+import { ApplyflairStore } from '@common/src/stores/studio/studios/applyflair'; //申请保留资质
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import type { IQueryResult } from '@/util/types.util';
+const applyflair = ApplyflairStore();
+const sysdictdata = DictDataStore();
+const unitStudioApply = UnitStudioApplyStore();
+const { proxy } = getCurrentInstance() as any;
+const router = useRouter();
+// #endregion
+// 列表数据
+let tableData: Ref<any[]> = ref([]);
+// 总数
+let total: Ref<number> = ref(0);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '序号', options: { type: 'index' } },
+  { label: '工作室名称', model: 'studio_name', isSearch: true },
+  { label: '依托单位名称', model: 'company_name' },
+  { label: '申请时间', model: 'apply_time' },
+  {
+    label: '审核状态',
+    model: 'status',
+    type: 'select',
+    format: (i) => {
+      let data = statusList.value.find((r) => r.dict_value == i);
+      if (data) return data.dict_label;
+    },
+    isSearch: true,
+  },
+]);
+// 操作
+let opera: Ref<any[]> = ref([
+  { label: '修改', method: 'edit', type: 'warning', display: (i) => i.status == '0' },
+  { label: '删除', method: 'del', type: 'danger', confirm: true },
+]);
+// 多选
+let selected: Ref<any[]> = ref([]);
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String }> = ref({ _id: '', status: '' });
+// 查询数据
+let searchForm: Ref<{}> = ref({});
+// 状态
+let statusList: Ref<any[]> = ref([]);
 
-<script setup lang="ts"></script>
-
-<style scoped></style>
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search({ skip, limit });
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    const { skip, limit } = e;
+    let info = { limit: limit, skip: skip, ...searchForm.value, company_id: unitInfo.value._id };
+    const res: IQueryResult = await applyflair.query(info);
+    tableData.value = res.data as any[];
+    total.value = res.total;
+  } else {
+    ElMessage({ type: 'warning', message: `用户未完成信息填报/信息填报未完成审核,无法查询相关信息` });
+  }
+};
+// 查询
+const partSearch = (form: { [x: string]: any }) => {
+  searchForm.value = form;
+  search({ skip, limit });
+};
+// 添加
+const toAdd = () => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    router.push({ path: '/unit/applyflair/add' });
+  } else {
+    ElMessage({ message: '用户未完成信息填报/信息填报未完成审核,无法查询相关信息', type: 'warning' });
+  }
+};
+// 修改
+const toEdit = (data: { _id: string }) => {
+  router.push({ path: '/unit/applyflair/add', query: { id: data._id } });
+};
+// 删除
+const toDel = async (data: { _id: string }) => {
+  const res: IQueryResult = await applyflair.del(data._id);
+  if (res.errcode == 0) {
+    ElMessage({ message: '删除信息成功', type: 'success' });
+    search({ skip, limit });
+  }
+};
+// 选择
+const handleSelect = () => {};
+// 查询其他信息
+const searchOther = async () => {
+  // 字典表---审核状态
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_status', is_use: '0' });
+  statusList.value = p1.data as [];
+};
+</script>
+<style lang="scss" scoped>
+.main {
+  .thr {
+    margin: 1vw 0 0 0;
+  }
+}
+</style>

+ 316 - 4
src/views/unit/builddesire/add.vue

@@ -1,11 +1,323 @@
 <template>
-  <div id="index">
+  <div id="add">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_back="true" @toBack="toBack"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="140px">
+            <el-col :span="24" class="form_1">
+              <el-col :span="24" class="title">一、工作室建设信息</el-col>
+              <el-col :span="24" class="info">
+                <el-form-item label="单位名称" prop="company_name">
+                  <el-input v-model="form.company_name" placeholder="请输入单位名称" disabled></el-input>
+                </el-form-item>
+                <el-form-item label="单位所在地" prop="address">
+                  <el-input v-model="form.address" placeholder="请输入单位所在地"></el-input>
+                </el-form-item>
+                <el-form-item label="单位性质" prop="nature">
+                  <el-select v-model="form.nature" filterable clearable placeholder="请选择单位性质" style="width: 100%">
+                    <el-option v-for="i in natureList" :key="i._id" :label="i.dict_label" :value="i.dict_value"></el-option>
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="拟解决技术难题或战略发展问题" prop="development">
+                  <el-input
+                    v-model="form.development"
+                    placeholder="请输入拟解决技术难题或战略发展问题"
+                    type="textarea"
+                    maxlength="500"
+                    show-word-limit
+                    :autosize="{ minRows: 6, maxRows: 6 }"
+                  ></el-input>
+                </el-form-item>
+                <el-form-item label="所属领域" prop="fields">
+                  <el-select v-model="form.fields" multiple clearable filterable placeholder="请选择所属领域" style="width: 100%">
+                    <el-option v-for="i in fieldList" :key="i._id" :label="i.dict_label" :value="i.dict_value"></el-option>
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="建设目标" prop="target">
+                  <el-input v-model="form.target" placeholder="请输入建设目标"></el-input>
+                </el-form-item>
+                <el-form-item label="联系人" prop="contact">
+                  <el-input v-model="form.contact" placeholder="请输入联系人"></el-input>
+                </el-form-item>
+                <el-form-item label="联系电话" prop="phone">
+                  <el-input v-model="form.phone" placeholder="请输入联系电话"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-col>
+            <el-col :span="24" class="form_1">
+              <el-col :span="24" class="title">二、科学家入驻要求</el-col>
+              <el-col :span="24" class="info">
+                <el-form-item label="专业技术职称" prop="zc">
+                  <el-select v-model="form.zc" filterable clearable placeholder="请选择专业技术职称" style="width: 100%">
+                    <el-option v-for="i in zcList" :key="i._id" :label="i.dict_label" :value="i.dict_value"></el-option>
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="专业领域" prop="zy_fields">
+                  <el-select v-model="form.zy_fields" multiple clearable filterable placeholder="请选择专业领域" style="width: 100%">
+                    <el-option v-for="i in fieldList" :key="i._id" :label="i.dict_label" :value="i.dict_value"></el-option>
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="研究方向" prop="direction">
+                  <el-button style="margin: 0 0 0.5vw 0" type="primary" size="small" @click.stop="addDriection()">添加</el-button>
+                  <el-table :data="form.direction" border size="small">
+                    <el-table-column type="index" label="序号" width="50" align="center"> </el-table-column>
+                    <el-table-column prop="name" label="名称" align="center">
+                      <template v-slot="scope">
+                        <el-input v-model="scope.row.name" placeholder="请输入研究方向名称"></el-input>
+                      </template>
+                    </el-table-column>
+                    <el-table-column label="操作" align="center" width="100">
+                      <template v-slot="scope">
+                        <el-button size="small" type="danger" @click="delDriection(scope.row)">删除</el-button>
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                </el-form-item>
+                <el-form-item label="其他要求" prop="other">
+                  <el-input
+                    v-model="form.other"
+                    placeholder="请输入其他要求"
+                    type="textarea"
+                    maxlength="500"
+                    show-word-limit
+                    :autosize="{ minRows: 6, maxRows: 6 }"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+            </el-col>
+            <el-col :span="24" class="form_1">
+              <el-col :span="24" class="title">三、是否公开<span>(公开:平台用户可在系统首页进行搜索查看;不公开:系统首页不展示此条数据;)</span></el-col>
+              <el-col :span="24" class="info">
+                <el-form-item label="是否公开" prop="is_use">
+                  <el-select v-model="form.is_use" filterable clearable placeholder="请选择是否公开" style="width: 100%">
+                    <el-option v-for="i in isuseList" :key="i._id" :label="i.dict_label" :value="i.dict_value"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-col>
+            <el-col :span="24" class="btn">
+              <el-button type="primary" size="small" @click="toSave(ruleFormRef)">提交发布</el-button>
+              <el-button type="danger" size="small" @click="reSave(ruleFormRef)">信息重置</el-button>
+            </el-col>
+          </el-form>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import store from '@/stores/counter';
+import moment from 'moment';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, reactive } from 'vue';
+import { ElMessage } from 'element-plus';
+import type { FormInstance, FormRules } from 'element-plus';
+import { useRoute } from 'vue-router';
+// #region 接口
+import { BuilddesireStore } from '@common/src/stores/studio/studios/builddesire'; // 发布工作室建设意愿
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import type { IQueryResult } from '@/util/types.util';
+const builddesire = BuilddesireStore();
+const unitStudioApply = UnitStudioApplyStore();
+const sysdictdata = DictDataStore();
+const ruleFormRef = ref<FormInstance>();
+let route = useRoute();
+// 必填项
+const rules = reactive<FormRules>({
+  company_name: [{ required: true, message: '请输入单位名称', trigger: 'blur' }],
+  address: [{ required: true, message: '请输入单位所在地', trigger: 'blur' }],
+  nature: [{ required: true, message: '请选择单位性质', trigger: 'change' }],
+  development: [{ required: true, message: '请输入拟解决技术难题或战略发展问题', trigger: 'blur' }],
+  fields: [{ required: true, message: '请选择所属领域', trigger: 'change' }],
+  target: [{ required: true, message: '请输入建设目标', trigger: 'blur' }],
+  contact: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
+  phone: [{ required: true, message: '请输入联系电话', trigger: 'change' }],
+  zc: [{ required: true, message: '请选择专业技术职称', trigger: 'change' }],
+  zy_fields: [{ required: true, message: '请选择专业领域', trigger: 'change' }],
+  direction: [{ required: false, message: '请选择专业领域', trigger: 'change' }],
+  other: [{ required: false, message: '请选择专业领域', trigger: 'blur' }],
+  is_use: [{ required: true, message: '请选择是否公开', trigger: 'change' }],
+});
+// 用户信息
+let user: Ref<{ _id: string }> = ref({ _id: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String; company: string; address: string }> = ref({ _id: '', status: '', company: '', address: '' });
+// 表单
+let form: Ref<{
+  _id: string;
+  company_name: string;
+  address: string;
+  nature: string;
+  development: string;
+  fields: Array<[]>;
+  target: string;
+  contact: string;
+  phone: string;
+  zc: string;
+  zy_fields: Array<[]>;
+  contdirectionact: string;
+  direction: Array<[]>;
+  other: string;
+  is_use: string;
+}> = ref({
+  _id: '',
+  company_name: '',
+  address: '',
+  nature: '',
+  development: '',
+  fields: [],
+  target: '',
+  contact: '',
+  phone: '',
+  zc: '',
+  zy_fields: [],
+  contdirectionact: '',
+  direction: [],
+  other: '',
+  is_use: '',
+});
+// 单位性质
+let natureList: Ref<any[]> = ref([]);
+// 领域
+let fieldList: Ref<any[]> = ref([]);
+// 是否启用
+let isuseList: Ref<any[]> = ref([]);
+// 专业技术职称
+let zcList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string };
+  await searchUnit();
+  await searchOther();
+  await search();
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async () => {
+  let data: any = {
+    user_id: user.value._id,
+    company_id: unitInfo.value._id,
+    company_name: unitInfo.value.company,
+    address: unitInfo.value.address,
+    fields: [],
+    zy_fields: [],
+    direction: [],
+  };
+  if (route.query && route.query.id) {
+    let id = route.query.id;
+    const res: IQueryResult = await builddesire.fetch(id);
+    if (res.errcode == 0) {
+      if (res.data)
+        form.value = res.data as {
+          _id: '';
+          company_name: '';
+          address: '';
+          nature: '';
+          development: '';
+          fields: [];
+          target: '';
+          contact: '';
+          phone: '';
+          zc: '';
+          zy_fields: [];
+          contdirectionact: '';
+          direction: [];
+          other: '';
+          is_use: '';
+        };
+    }
+  } else {
+    form.value = { ...data };
+  }
+};
+// 研究方向添加
+const addDriection = () => {
+  let direction: any = form.value.direction;
+  if (direction.length >= 5) {
+    ElMessage({ message: `研究方向最多添加五个`, type: 'error' });
+  } else {
+    direction.push({ id: moment().valueOf(), name: '' });
+  }
+  form.value.direction = direction;
+};
+// 研究方向删除
+const delDriection = (e: { id: '' }) => {
+  let direction = form.value.direction.filter((i: any) => i.id != e.id);
+  form.value.direction = direction;
+};
+// 返回
+const toBack = () => {
+  window.history.go(-1);
+};
+const toSave = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      let res: IQueryResult;
+      if (form.value._id) res = await builddesire.update(form.value);
+      else res = await builddesire.create(form.value);
+      if (res.errcode == 0) {
+        ElMessage({ type: 'success', message: '维护信息成功' });
+        toBack();
+      } else ElMessage({ type: 'warning', message: `${res.errmsg}` });
+    } else {
+      console.log('error submit!', fields);
+    }
+  });
+};
+// 取消提交
+const reSave = (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  formEl.resetFields();
+};
+// 查询其他信息
+const searchOther = async () => {
+  // 单位性质
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 's-builddesire-nature' });
+  natureList.value = p1.data as [];
+  // 领域
+  const p2: IQueryResult = await sysdictdata.query({ dict_type: 'studio_field' });
+  fieldList.value = p2.data as [];
+  // 是否启用
+  const p3: IQueryResult = await sysdictdata.query({ dict_type: 's-builddesire-isuse' });
+  isuseList.value = p3.data as [];
+  // 专业技术职称
+  const p4: IQueryResult = await sysdictdata.query({ dict_type: 's-builddesire-zc' });
+  zcList.value = p4.data as [];
+};
+</script>
 
-<style scoped></style>
+<style lang="scss" scoped>
+.main {
+  .two {
+    padding: 0 0 10px 0;
+    .form_1 {
+      .title {
+        margin: 0 0 15px 0;
+        font-size: 20px;
+        font-family: monospace;
+        font-weight: bold;
+        span {
+          font-size: 12px;
+          color: #858585;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+    }
+  }
+}
+</style>

+ 239 - 7
src/views/unit/builddesire/index.vue

@@ -1,11 +1,243 @@
 <template>
   <div id="index">
-    <el-row>
-      <el-col :span="24" class="main"> test </el-col>
-    </el-row>
+    <el-col class="main animate__animated animate__backInRight">
+      <el-col :span="24" class="one">
+        <component :is="partsSearch" :is_search="true" :fields="fields" @search="partSearch">
+          <template #nature>
+            <el-option v-for="i in natureList" :key="i.dict_value" :label="i.dict_label" :value="i.dict_value"></el-option>
+          </template>
+        </component>
+      </el-col>
+      <el-col :span="24" class="two">
+        <component :is="Btn1" @toAdd="toAdd"></component>
+      </el-col>
+      <el-col :span="24" class="thr">
+        <component
+          :is="CTable"
+          :fields="fields"
+          :opera="opera"
+          :select="false"
+          :selected="selected"
+          @handleSelect="handleSelect"
+          @query="search"
+          :data="tableData"
+          :total="total"
+          @show="toShow"
+          @edit="toEdit"
+          @del="toDel"
+        >
+        </component>
+      </el-col>
+    </el-col>
   </div>
+  <component :is="CDialog" :dialog="dialog" @handleClose="handleClose">
+    <template v-slot:info>
+      <el-col :span="24" class="dialog_one" v-if="dialog.type == '1'">
+        <el-col :span="24" class="one_1">
+          <span>当前信息状态:</span>
+          <span>{{ form.is_use == '0' ? '公开' : '不公开' }}</span>
+        </el-col>
+        <el-col :span="24" class="one_2">
+          <p>公开:平台用户可在系统首页进行搜索查看;</p>
+          <p>不公开:如不想在系统首页公开展示或工作室已公示,批准建设,可选不公开;</p>
+        </el-col>
+        <el-col :span="24" class="btn">
+          <el-button type="primary" size="small" @click="useSave('0')">公开</el-button>
+          <el-button type="danger" size="small" @click="useSave('1')">不公开</el-button>
+        </el-col>
+      </el-col>
+    </template>
+  </component>
 </template>
-
-<script setup lang="ts"></script>
-
-<style scoped></style>
+<script setup lang="ts">
+import store from '@/stores/counter';
+import { ElMessage } from 'element-plus';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CTable from '@/components/c-table.vue';
+import CDialog from '@/components/c-dialog.vue';
+import Btn1 from '@/components/btn-1.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+// #region 接口
+import { BuilddesireStore } from '@common/src/stores/studio/studios/builddesire'; // 发布工作室建设意愿
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import type { IQueryResult } from '@/util/types.util';
+const builddesire = BuilddesireStore();
+const unitStudioApply = UnitStudioApplyStore();
+const sysdictdata = DictDataStore();
+const { proxy } = getCurrentInstance() as any;
+const router = useRouter();
+// #endregion
+// 列表数据
+let tableData: Ref<any[]> = ref([]);
+// 总数
+let total: Ref<number> = ref(0);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '序号', options: { type: 'index' } },
+  { label: '单位名称', model: 'company_name', isSearch: true },
+  {
+    label: '单位性质',
+    model: 'nature',
+    type: 'select',
+    format: (i) => {
+      let data = natureList.value.find((r) => r.dict_value == i);
+      if (data) return data.dict_label;
+    },
+    isSearch: true,
+  },
+  { label: '联系人', model: 'contact' },
+  { label: '联系电话', model: 'phone', isSearch: true },
+  { label: '单位所在地', model: 'address' },
+  {
+    label: '是否公开',
+    model: 'is_use',
+    format: (i) => {
+      let data = isuseList.value.find((r) => r.dict_value == i);
+      if (data) return data.dict_label;
+    },
+  },
+]);
+// 操作
+let opera: Ref<any[]> = ref([
+  { label: '公开/不公开', method: 'show', type: 'warning' },
+  { label: '修改', method: 'edit' },
+  { label: '删除', method: 'del', confirm: true, type: 'danger' },
+]);
+// 多选
+let selected: Ref<any[]> = ref([]);
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 查询数据
+let searchForm: Ref<{}> = ref({});
+// 弹框
+const dialog: Ref<{ type: string; show: boolean; title: string }> = ref({ type: '1', show: false, title: '信息管理' });
+// 审核表单
+let form: Ref<{ is_use: string; _id: string }> = ref({ is_use: '', _id: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String }> = ref({ _id: '', status: '' });
+// 单位性质
+let natureList: Ref<any[]> = ref([]);
+// 领域
+let fieldList: Ref<any[]> = ref([]);
+// 是否启用
+let isuseList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search({ skip, limit });
+});
+// 查询依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    const { skip, limit } = e;
+    let info = { limit: limit, skip: skip, ...searchForm.value, company_id: unitInfo.value._id };
+    const res: IQueryResult = await builddesire.query(info);
+    tableData.value = res.data as any[];
+    total.value = res.total;
+  } else {
+    ElMessage({ type: 'warning', message: `用户未完成信息填报/信息填报未完成审核,无法查询相关信息` });
+  }
+};
+// 查询
+const partSearch = (form: { [x: string]: any }) => {
+  searchForm.value = form;
+  search({ skip, limit });
+};
+// 添加
+const toAdd = () => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    router.push({ path: '/unit/builddesire/add' });
+  } else {
+    ElMessage({ message: '用户未完成信息填报/信息填报未完成审核,无法查询相关信息', type: 'warning' });
+  }
+};
+// 公开/不公开
+const toShow = async (data: { is_use: ''; _id: '' }) => {
+  form.value = data;
+  dialog.value = { title: '信息管理', show: true, type: '1' };
+};
+// 修改
+const toEdit = (data: { _id: string }) => {
+  router.push({ path: '/unit/builddesire/add', query: { id: data._id } });
+};
+// 删除
+const toDel = async (data: { _id: string }) => {
+  const res: IQueryResult = await builddesire.del(data._id);
+  if (res.errcode == 0) {
+    ElMessage({ message: '删除信息成功', type: 'success' });
+    search({ skip, limit });
+  }
+};
+// 提交
+const useSave = async (data: string) => {
+  let arr = await builddesire.update({ _id: form.value._id, is_use: data });
+  if (arr.errcode == 0) {
+    ElMessage({ type: 'success', message: '信息维护成功' });
+    handleClose();
+  }
+};
+// 关闭弹窗
+const handleClose = () => {
+  form.value = { is_use: '', _id: '' };
+  search({ skip, limit });
+  dialog.value = { title: '信息管理', show: false, type: '' };
+};
+// 选择
+const handleSelect = () => {};
+// 查询其他信息
+const searchOther = async () => {
+  // 单位性质
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 's-builddesire-nature' });
+  natureList.value = p1.data as [];
+  // 领域
+  const p2: IQueryResult = await sysdictdata.query({ dict_type: 'studio_field' });
+  fieldList.value = p2.data as [];
+  // 是否启用
+  const p3: IQueryResult = await sysdictdata.query({ dict_type: 's-builddesire-isuse' });
+  isuseList.value = p3.data as [];
+};
+</script>
+<style lang="scss" scoped>
+.main {
+  .thr {
+    margin: 1vw 0 0 0;
+  }
+}
+.dialog_one {
+  .one_1 {
+    margin: 0 0 15px 0;
+    span {
+      font-size: 16px;
+      font-weight: bold;
+      font-family: monospace;
+    }
+    span:nth-child(2) {
+      color: #ff0000;
+    }
+  }
+  .one_2 {
+    margin: 0 0 15px 0;
+    p {
+      margin: 0 0 5px 0;
+      font-size: 14px;
+    }
+  }
+  .btn {
+    text-align: center;
+  }
+}
+</style>

+ 26 - 5
src/views/unit/contactoffice/index.vue

@@ -1,11 +1,32 @@
 <template>
-  <div id="index">
+  <div id="info">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <p v-html="form.content"></p>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
+<script setup lang="ts">
+import partsSearch from '@/components/c-search.vue';
+import type { Ref } from 'vue';
+import { ref, onMounted } from 'vue';
+import { ContactofficeStore } from '@common/src/stores/studio/other/contactoffice'; // 联系处室
+import type { IQueryResult } from '@/util/types.util';
+const contactoffice = ContactofficeStore();
+let form: Ref<{ content: string }> = ref({ content: '' });
+onMounted(async () => {
+  await search();
+});
+const search = async () => {
+  const res: IQueryResult = await contactoffice.query();
+  form.value = res.data[0] as { content: string };
+};
+</script>
 
-<script setup lang="ts"></script>
-
-<style scoped></style>
+<style lang="scss" scoped></style>

+ 138 - 3
src/views/unit/demand/add.vue

@@ -1,11 +1,146 @@
 <template>
-  <div id="index">
+  <div id="add">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_back="true" @toBack="toBack"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="CForm" :fields="fields" :rules="rules" :form="form" labelWidth="auto" @save="toSave">
+            <template #fields>
+              <el-option v-for="item in fieldList" :key="item.dict_value" :label="item.dict_label" :value="item.dict_value"></el-option>
+            </template>
+            <template #is_use>
+              <el-option v-for="item in isuseList" :key="item.dict_value" :label="item.dict_label" :value="item.dict_value"></el-option>
+            </template>
+            <template #file>
+              <component :is="CFile" model="file" :limit="limit" :url="url" :list="form.file" @change="onChange"></component>
+            </template>
+            <template #content>
+              <component :is="WangEditor" v-model="form.content" url="/files/studioadmin/other/upload"></component>
+            </template>
+          </component>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import store from '@/stores/counter';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CForm from '@/components/c-form.vue';
+import CFile from '@/components/c-upload.vue';
+import WangEditor from '@/components/wang-editor.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, reactive } from 'vue';
+import type { FormRules } from 'element-plus';
+import { ElMessage } from 'element-plus';
+import { useRoute } from 'vue-router';
+// #region 接口
+import { TecholdemandStore } from '@common/src/stores/studio/supplydemand/techoldemand'; //技术需求
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; //个人账号申请科学家工作室权限表
+import type { IQueryResult } from '@/util/types.util';
+const techoldemand = TecholdemandStore();
+const sysdictdata = DictDataStore();
+const unitStudioApply = UnitStudioApplyStore();
+let route = useRoute();
+// 必填项
+const rules = reactive<FormRules>({
+  phone: [{ required: true, message: '请输入联系方式', trigger: 'blur' }],
+  title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
+  date: [{ required: true, message: '请选择发布时间', trigger: 'change' }],
+  fields: [{ required: true, message: '请选择专业领域', trigger: 'change' }],
+  file: [{ required: true, message: '请上传文件信息', trigger: 'change' }],
+  content: [{ required: true, message: '请输入信息内容', trigger: 'blur' }],
+  stop_date: [{ required: true, message: '请选择需求截止时间', trigger: 'change' }],
+});
+// 表单
+let fields: Ref<any[]> = ref([
+  { label: '依托单位名称', model: 'company_name', options: { readonly: true } },
+  { label: '联系方式', model: 'phone' },
+  { label: '标题', model: 'title' },
+  { label: '发布时间', model: 'date', type: 'date' },
+  { label: '专业领域', model: 'fields', type: 'selectMany' },
+  { label: '文件信息', model: 'file', custom: true },
+  { label: '信息内容', model: 'content', custom: true },
+  { label: '需求截止时间', model: 'stop_date', type: 'date' },
+  { label: '是否启用', model: 'is_use', type: 'select' },
+]);
+let limit: Ref<number> = ref(1);
+let url: Ref<string> = ref('/files/studioadmin/demand/upload');
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String; company: string; phone: string }> = ref({ _id: '', status: '', company: '', phone: '' });
+// 表单
+let form: Ref<{ content: string; file: Array<[]> }> = ref({ content: '', file: [] });
+// 行业领域
+let fieldList: Ref<any[]> = ref([]);
+// 是否启用
+let isuseList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search();
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async () => {
+  let data = {
+    user_id: unitInfo.value._id,
+    company_name: unitInfo.value.company,
+    phone: unitInfo.value.phone,
+    content: '',
+    file: [],
+  };
+  if (route.query && route.query.id) {
+    let id = route.query.id;
+    const res: IQueryResult = await techoldemand.fetch(id);
+    if (res.errcode == 0) {
+      if (res.data) form.value = res.data as { content: string; file: Array<[]> };
+    }
+  } else {
+    form.value = { ...data };
+  }
+};
+// 返回
+const toBack = () => {
+  window.history.go(-1);
+};
+// 上传
+const onChange = (e: { model: string; value: Array<[]> }) => {
+  const { model, value } = e;
+  form.value[model] = value;
+};
+// 添加
+const toSave = async (data: { _id: string }) => {
+  let res: IQueryResult;
+  if (data._id) res = await techoldemand.update(data);
+  else res = await techoldemand.create(data);
+  if (res.errcode == 0) {
+    ElMessage({ type: 'success', message: '维护信息成功' });
+    toBack();
+  } else ElMessage({ type: 'warning', message: `${res.errmsg}` });
+};
+// 查询其他信息
+const searchOther = async () => {
+  // 字典表---领域
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_field' });
+  fieldList.value = p1.data as [];
+  // 是否启用
+  const p2: IQueryResult = await sysdictdata.query({ dict_type: 'sys_yes_no' });
+  isuseList.value = p2.data as [];
+};
+</script>
 
 <style scoped></style>

+ 181 - 4
src/views/unit/demand/index.vue

@@ -1,11 +1,188 @@
 <template>
   <div id="index">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_search="true" :fields="fields" @search="partSearch">
+            <template #status>
+              <el-option v-for="i in statusList" :key="i.dict_value" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+          </component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="Btn1" @toAdd="toAdd"></component>
+        </el-col>
+        <el-col :span="24" class="thr">
+          <component
+            :is="CTable"
+            :fields="fields"
+            :opera="opera"
+            :select="false"
+            :selected="selected"
+            @handleSelect="handleSelect"
+            @query="search"
+            :data="tableData"
+            :total="total"
+            @view="toView"
+            @edit="toEdit"
+            @del="toDel"
+          >
+            <template #is_use="{ row, item }">
+              <el-button :type="row[item.model] == 'Y' ? 'primary' : 'danger'" size="mini" @click="toUse(row)">{{
+                row[item.model] == 'Y' ? '是' : '否'
+              }}</el-button>
+            </template>
+          </component>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
+<script setup lang="ts">
+import store from '@/stores/counter';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CTable from '@/components/c-table.vue';
+import Btn1 from '@/components/btn-1.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { ElMessage } from 'element-plus';
+import { useRouter } from 'vue-router';
+// #region 接口
+import { TecholdemandStore } from '@common/src/stores/studio/supplydemand/techoldemand'; //技术需求
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import type { IQueryResult } from '@/util/types.util';
+const techoldemand = TecholdemandStore();
+const sysdictdata = DictDataStore();
+const unitStudioApply = UnitStudioApplyStore();
+const { proxy } = getCurrentInstance() as any;
+const router = useRouter();
+// #endregion
+// 列表数据
+let tableData: Ref<any[]> = ref([]);
+// 总数
+let total: Ref<number> = ref(0);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '序号', options: { type: 'index' } },
+  { label: '标题', model: 'title', isSearch: true },
+  { label: '发布时间', model: 'date' },
+  { label: '依托单位名称', model: 'company_name', isSearch: true },
+  { label: '联系方式', model: 'phone', isSearch: true },
+  {
+    label: '审核状态',
+    model: 'status',
+    type: 'select',
+    format: (i) => {
+      let data = statusList.value.find((r) => r.dict_value == i);
+      if (data) return data.dict_label;
+    },
+    isSearch: true,
+  },
+  { label: '需求截止时间', model: 'stop_date' },
+  { label: '是否启用', model: 'is_use', custom: true },
+]);
+// 操作
+let opera: Ref<any[]> = ref([
+  { label: '详情', method: 'view' },
+  { label: '修改', method: 'edit', type: 'warning', display: (i) => i.status == '0' },
+  { label: '删除', method: 'del', type: 'danger', confirm: true },
+]);
+// 多选
+let selected: Ref<any[]> = ref([]);
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String }> = ref({ _id: '', status: '' });
+// 查询数据
+let searchForm: Ref<{}> = ref({});
+// 状态
+let statusList: Ref<any[]> = ref([]);
+// 是否使用
+let isuseList: Ref<any[]> = ref([]);
 
-<script setup lang="ts"></script>
-
-<style scoped></style>
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search({ skip, limit });
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    const { skip, limit } = e;
+    let info = { limit: limit, skip: skip, ...searchForm.value, company_id: unitInfo.value._id };
+    const res: IQueryResult = await techoldemand.query(info);
+    tableData.value = res.data as any[];
+    total.value = res.total;
+  } else {
+    ElMessage({ type: 'warning', message: `用户未完成信息填报/信息填报未完成审核,无法查询相关信息` });
+  }
+};
+// 查询
+const partSearch = (form: { [x: string]: any }) => {
+  searchForm.value = form;
+  search({ skip, limit });
+};
+// 添加
+const toAdd = () => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    router.push({ path: '/unit/demand/add' });
+  } else {
+    ElMessage({ message: '用户未完成信息填报/信息填报未完成审核,无法查询相关信息', type: 'warning' });
+  }
+};
+// 是否启用
+const toUse = async (data: { is_use: string }) => {
+  data.is_use = data.is_use == 'Y' ? 'N' : 'Y';
+  const res: IQueryResult = await techoldemand.update(data);
+  if (res.errcode == 0) {
+    ElMessage({ message: '维护信息成功', type: 'success' });
+    search({ skip, limit });
+  }
+};
+// 查看
+const toView = (data: { _id: string }) => {
+  router.push({ path: '/unit/demand/info', query: { id: data._id } });
+};
+// 修改
+const toEdit = (data: { _id: string }) => {
+  router.push({ path: '/unit/demand/add', query: { id: data._id } });
+};
+// 删除
+const toDel = async (data: { _id: string }) => {
+  const res: IQueryResult = await techoldemand.del(data._id);
+  if (res.errcode == 0) {
+    ElMessage({ message: '删除信息成功', type: 'success' });
+    search({ skip, limit });
+  }
+};
+// 选择
+const handleSelect = () => {};
+// 查询其他信息
+const searchOther = async () => {
+  // 字典表---审核状态
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_status', is_use: '0' });
+  statusList.value = p1.data as [];
+  // 是否启用
+  const p2: IQueryResult = await sysdictdata.query({ dict_type: 'sys_yes_no' });
+  isuseList.value = p2.data as [];
+};
+</script>
+<style lang="scss" scoped>
+.main {
+  .thr {
+    margin: 1vw 0 0 0;
+  }
+}
+</style>

+ 37 - 5
src/views/unit/demand/info.vue

@@ -1,11 +1,43 @@
 <template>
-  <div id="index">
+  <div id="info">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_back="true" @toBack="toBack()"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="demandInfo" :info="info"></component>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
+<script setup lang="ts">
+import partsSearch from '@/components/c-search.vue';
+import demandInfo from '@/components/common/demand/info.vue';
+import { useRoute } from 'vue-router';
+import type { Ref } from 'vue';
+import { ref, onMounted } from 'vue';
+import { TecholdemandStore } from '@common/src/stores/studio/supplydemand/techoldemand'; // 列表
+import type { IQueryResult } from '@/util/types.util';
+const techoldemand = TecholdemandStore();
+let route = useRoute();
+let info: Ref<{}> = ref({});
+onMounted(async () => {
+  await search();
+});
+// 查询
+const search = async () => {
+  if (route.query && route.query.id) {
+    let id = route.query.id;
+    const res: IQueryResult = await techoldemand.fetch(id);
+    info.value = res.data as {};
+  }
+};
+// 返回
+const toBack = () => {
+  window.history.go(-1);
+};
+</script>
 
-<script setup lang="ts"></script>
-
-<style scoped></style>
+<style lang="scss" scoped></style>

+ 253 - 3
src/views/unit/scientist/add.vue

@@ -1,11 +1,261 @@
 <template>
-  <div id="index">
+  <div id="add">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_back="true" @toBack="toBack"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="CForm" :fields="fields" :rules="rules" :form="form" @dataChange="dataChange" labelWidth="auto" @save="toSave">
+            <template #scientist_id>
+              <el-option v-for="i in scientistList" :key="i.id" :label="i.name" :value="i._id"></el-option>
+            </template>
+            <template #fields>
+              <el-option v-for="i in fieldList" :key="i.dict_value" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+            <template #direction>
+              <span v-for="(i, index) in form.direction" :key="index" class="direction">
+                <span>{{ index + 1 }}.</span>{{ i.name }}
+              </span>
+            </template>
+            <template #studio_id>
+              <el-option v-for="i in studioList" :key="i._id" :label="i.apply_name || i.name" :value="i._id"></el-option>
+            </template>
+            <template #settle_file>
+              <component :is="CFile" model="settle_file" :limit="limit" :url="url" :list="form.settle_file" @change="onChange"></component>
+            </template>
+            <template #team>
+              <el-col :span="24" class="team_1">
+                <el-button type="primary" size="small" @click="addTeam()">添加团队成员</el-button>
+                <el-col :span="24" class="team_txt">团队成员人数不可超过15人!</el-col>
+              </el-col>
+              <el-col :span="24" class="team_2">
+                <el-table :data="form.team" border size="small">
+                  <el-table-column type="index" label="序号" width="50" align="center"> </el-table-column>
+                  <el-table-column prop="name" label="姓名" align="center">
+                    <template v-slot="scope">
+                      <el-input v-model="scope.row.name" placeholder="请输入姓名"></el-input>
+                    </template>
+                  </el-table-column>
+                  <el-table-column prop="company" label="工作单位" align="center">
+                    <template v-slot="scope">
+                      <el-input v-model="scope.row.company" placeholder="请输入工作单位"></el-input>
+                    </template>
+                  </el-table-column>
+                  <el-table-column prop="zc" label="职称" align="center">
+                    <template v-slot="scope">
+                      <el-input v-model="scope.row.zc" placeholder="请输入职称"></el-input>
+                    </template>
+                  </el-table-column>
+                  <el-table-column prop="phone" label="手机号码" align="center">
+                    <template v-slot="scope">
+                      <el-input v-model="scope.row.phone" placeholder="请输入手机号码"></el-input>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="操作" align="center" width="100" v-if="form.status == null">
+                    <template v-slot="scope">
+                      <el-button size="small" type="danger" @click="delTeam(scope.row)">删除</el-button>
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </el-col>
+            </template>
+          </component>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import store from '@/stores/counter';
+import moment from 'moment';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CForm from '@/components/c-form.vue';
+import CFile from '@/components/c-upload.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, reactive } from 'vue';
+import type { FormRules } from 'element-plus';
+import { ElMessage } from 'element-plus';
+import { useRoute } from 'vue-router';
+// #region 接口
+import { ScientistsettleStore } from '@common/src/stores/studio/studios/scientistsettle'; // 入驻科学家工作室
+import { StudioStore } from '@common/src/stores/studio/studios/studio'; // 工作室
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import { UserStudioApplyStore } from '@common/src/stores/studio/role/userStudioApply'; //个人账号申请科学家工作室权限表
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import type { IQueryResult } from '@/util/types.util';
+const studio = StudioStore();
+const unitStudioApply = UnitStudioApplyStore();
+const scientistsettle = ScientistsettleStore();
+const sysdictdata = DictDataStore();
+const userStudioApply = UserStudioApplyStore();
+let route = useRoute();
+// 必填项
+const rules = reactive<FormRules>({});
+// 表单
+let fields: Ref<any[]> = ref([
+  { label: '依托单位名称', model: 'company_name', options: { disabled: true } },
+  {
+    label: '科学家工作室',
+    model: 'studio_id',
+    type: 'select',
+    format: (i) => {
+      let data = studioList.value.find((r) => r._id == i);
+      if (data) return data.name;
+    },
+    options: { disabled: true },
+  },
+  {
+    label: '科学家姓名',
+    model: 'scientist_id',
+    type: 'select',
+    format: (i) => {
+      let data = scientistList.value.find((r) => r._id == i);
+      if (data) return data.name;
+    },
+    options: { disabled: true },
+  },
+  { label: '工作单位', model: 'company', options: { disabled: true } },
+  { label: '职称', model: 'zc', options: { disabled: true } },
+  { label: '专业领域', model: 'fields', type: 'selectMany', options: { disabled: true } },
+  { label: '研究方向', model: 'direction', custom: true },
+  { label: '文件', model: 'settle_file', custom: true },
+  { label: '团队成员', model: 'team', custom: true },
+]);
+let limit: Ref<number> = ref(1);
+let url: Ref<string> = ref('/files/studioadmin/support/upload');
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String; company: string }> = ref({ _id: '', status: '', company: '' });
+// 表单
+let form: Ref<{
+  scientist_name: string;
+  user_id: string;
+  company: string;
+  zc: string;
+  fields: Array<any>;
+  direction: Array<any>;
+  settle_file: Array<any>;
+  team: Array<any>;
+  status: string;
+}> = ref({
+  scientist_name: '',
+  user_id: '',
+  company: '',
+  zc: '',
+  fields: [],
+  direction: [],
+  settle_file: [],
+  status: '',
+  team: [],
+});
+// 行业领域
+let fieldList: Ref<any[]> = ref([]);
+// 科学家信息
+let scientistList: Ref<any[]> = ref([]);
+// 工作室
+let studioList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchOther();
+  await searchUnit();
+  await search();
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async () => {
+  let data = {
+    company_id: unitInfo.value._id,
+    company_name: unitInfo.value.company,
+    scientist_name: '',
+    user_id: '',
+    company: '',
+    zc: '',
+    fields: [],
+    direction: [],
+    settle_file: [],
+    status: '',
+    team: [],
+  };
+  if (route.query && route.query.id) {
+    let id = route.query.id;
+    const res: IQueryResult = await scientistsettle.fetch(id);
+    if (res.errcode == 0) {
+      if (res.data)
+        form.value = res.data as { scientist_name: ''; user_id: ''; company: ''; zc: ''; fields: []; direction: []; settle_file: []; status: ''; team: [] };
+    }
+  } else {
+    form.value = { ...data };
+  }
+};
+// 添加成员信息
+const addTeam = () => {
+  let team = form.value.team;
+  if (team.length >= 15) {
+    ElMessage({ message: `团队成员人数不可超过15人!`, type: 'error' });
+  } else {
+    team.push({ id: moment().valueOf(), name: '' });
+  }
+  form.value.team = team;
+};
+// 团队成员信息删除
+const delTeam = (e) => {
+  let team = form.value.team.filter((i: any) => i.id != e.id);
+  form.value.team = team;
+};
+const dataChange = (model, value) => {
+  if (model == 'scientist_id') {
+    let data = scientistList.value.find((i) => i._id == value);
+    if (data) {
+      form.value.scientist_name = data.name;
+      form.value.user_id = data.user_id;
+      form.value.company = data.company;
+      form.value.zc = data.zc;
+      form.value.fields = data.fields;
+      form.value.direction = data.direction;
+    }
+  }
+};
+// 返回
+const toBack = () => {
+  window.history.go(-1);
+};
+// 上传
+const onChange = (e: { model: string; value: Array<[]> }) => {
+  const { model, value } = e;
+  form.value[model] = value;
+};
+// 添加
+const toSave = async (data: { _id: string }) => {
+  let res: IQueryResult;
+  if (data._id) res = await scientistsettle.update(data);
+  else res = await scientistsettle.create(data);
+  if (res.errcode == 0) {
+    ElMessage({ type: 'success', message: '维护信息成功' });
+    toBack();
+  } else ElMessage({ type: 'warning', message: `${res.errmsg}` });
+};
+// 查询其他信息
+const searchOther = async () => {
+  //科学家信息
+  const p1: IQueryResult = await userStudioApply.query({ status: '1' });
+  scientistList.value = p1.data as [];
+  // 领域
+  const p2: IQueryResult = await sysdictdata.query({ dict_type: 'studio_field' });
+  fieldList.value = p2.data as [];
+  // 工作室
+  const p3: IQueryResult = await studio.query({ user_id: user.value._id });
+  studioList.value = p3.data as [];
+};
+</script>
 
 <style scoped></style>

+ 129 - 7
src/views/unit/scientist/index.vue

@@ -1,11 +1,133 @@
 <template>
   <div id="index">
-    <el-row>
-      <el-col :span="24" class="main"> test </el-col>
-    </el-row>
+    <el-col class="main animate__animated animate__backInRight">
+      <el-col :span="24" class="one">
+        <component :is="partsSearch" :is_search="true" :fields="fields" @search="partSearch">
+          <template #studio_id>
+            <el-option v-for="i in studioList" :key="i._id" :label="i.name" :value="i._id"></el-option>
+          </template>
+        </component>
+      </el-col>
+      <el-col :span="24" class="two">
+        <component
+          :is="CTable"
+          :fields="fields"
+          :opera="opera"
+          :select="false"
+          :selected="selected"
+          @handleSelect="handleSelect"
+          @query="search"
+          :data="tableData"
+          :total="total"
+          @edit="toEdit"
+        >
+        </component>
+      </el-col>
+    </el-col>
   </div>
 </template>
-
-<script setup lang="ts"></script>
-
-<style scoped></style>
+<script setup lang="ts">
+import store from '@/stores/counter';
+import { ElMessage } from 'element-plus';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CTable from '@/components/c-table.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+// #region 接口
+import { ScientistsettleStore } from '@common/src/stores/studio/studios/scientistsettle'; // 入驻科学家工作室
+import { StudioStore } from '@common/src/stores/studio/studios/studio'; // 工作室
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import type { IQueryResult } from '@/util/types.util';
+const studio = StudioStore();
+const unitStudioApply = UnitStudioApplyStore();
+const scientistsettle = ScientistsettleStore();
+const { proxy } = getCurrentInstance() as any;
+const router = useRouter();
+// #endregion
+// 列表数据
+let tableData: Ref<any[]> = ref([]);
+// 总数
+let total: Ref<number> = ref(0);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '序号', options: { type: 'index' } },
+  {
+    label: '科学家工作室',
+    model: 'studio_id',
+    type: 'select',
+    format: (i) => {
+      let data = studioList.value.find((r) => r._id == i);
+      if (data) return data.name;
+    },
+    isSearch: true,
+  },
+  { label: '科学家名称', model: 'scientist_name', isSearch: true },
+  { label: '工作单位', model: 'company', isSearch: true },
+  { label: '职称', model: 'zc', isSearch: true },
+]);
+// 操作
+let opera: Ref<any[]> = ref([{ label: '修改', method: 'edit' }]);
+// 多选
+let selected: Ref<any[]> = ref([]);
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 查询数据
+let searchForm: Ref<{}> = ref({});
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String }> = ref({ _id: '', status: '' });
+// 工作室
+let studioList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search({ skip, limit });
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    const { skip, limit } = e;
+    let info = { limit: limit, skip: skip, ...searchForm.value, company_id: unitInfo.value._id };
+    const res: IQueryResult = await scientistsettle.query(info);
+    tableData.value = res.data as any[];
+    total.value = res.total;
+  } else {
+    ElMessage({ type: 'warning', message: `用户未完成信息填报/信息填报未完成审核,无法查询相关信息` });
+  }
+};
+// 查询
+const partSearch = (form: { [x: string]: any }) => {
+  searchForm.value = form;
+  search({ skip, limit });
+};
+// 修改
+const toEdit = (data: { _id: string }) => {
+  router.push({ path: '/unit/scientist/add', query: { id: data._id } });
+};
+// 选择
+const handleSelect = () => {};
+// 查询其他信息
+const searchOther = async () => {
+  // 工作室
+  const p1: IQueryResult = await studio.query({ user_id: user.value._id });
+  studioList.value = p1.data as [];
+};
+</script>
+<style lang="scss" scoped>
+.main {
+  .thr {
+    margin: 1vw 0 0 0;
+  }
+}
+</style>

+ 215 - 4
src/views/unit/studio/add.vue

@@ -1,11 +1,222 @@
 <template>
-  <div id="index">
+  <div id="add">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_back="true" @toBack="toBack"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <el-col :span="24" class="two_1">
+            <el-steps :active="active" finish-status="finish" process-status="success" align-center>
+              <el-step title="依托单位信息填报"></el-step>
+              <el-step title="提交科学家入驻协议"></el-step>
+              <el-step title="提交工作室建设方案"></el-step>
+              <el-step title="科技厅考察,评审"></el-step>
+              <el-step title="公示,批准建设"></el-step>
+            </el-steps>
+          </el-col>
+          <el-col :span="24" class="two_2">
+            <form1 v-if="active == 0" :form="form" :fieldList="fieldList" @toStep="toStep"></form1>
+            <form2
+              v-else-if="active == 1"
+              :form="form"
+              :fieldList="fieldList"
+              @toStep="toStep"
+              @searchSci="searchSci"
+              :sciInfoList="sciInfoList"
+              @scChange="scChange"
+            ></form2>
+            <form3 v-else-if="active == 2" :form="form" @toStep="toStep" @toSubmit="toSubmit"></form3>
+            <component v-else-if="active == 3 || active == 4" :is="studioInfo" :info="form"></component>
+          </el-col>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import store from '@/stores/counter';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import studioInfo from '@/components/common/studio/info.vue';
+import form1 from './parts/form-1.vue';
+import form2 from './parts/form-2.vue';
+import form3 from './parts/form-3.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted } from 'vue';
+import { useRoute } from 'vue-router';
+import { ElMessage } from 'element-plus';
+// #region 接口
+import { StudioStore } from '@common/src/stores/studio/studios/studio'; //工作室
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import { UsersStore } from '@common/src/stores/users/users'; //用户
+import { UserStudioApplyStore } from '@common/src/stores/studio/role/userStudioApply'; // 个人账号申请科学家工作室权限表
+import { ScientistsettleStore } from '@common/src/stores/studio/studios/scientistsettle'; //入驻科学家工作室
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import type { IQueryResult } from '@/util/types.util';
+const studio = StudioStore();
+const unitStudioApply = UnitStudioApplyStore();
+const users = UsersStore();
+const userStudioApply = UserStudioApplyStore();
+const scientistsettle = ScientistsettleStore();
+const sysdictdata = DictDataStore();
+let route = useRoute();
+let active: Ref<number> = ref(0);
+// 用户信息
+let user: Ref<{ _id: string }> = ref({ _id: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String; company: string; address: string }> = ref({ _id: '', status: '', company: '', address: '' });
+// 表单
+let form: Ref<{ scientist_id: string; scientistinfo_id: string; scientist_name: string; team: Array<[]> }> = ref({
+  scientist_id: '',
+  scientistinfo_id: '',
+  scientist_name: '',
+  team: [],
+});
+// 领域
+let fieldList: Ref<any[]> = ref([]);
+// 科学家信息表
+let sciInfoList: Ref<any[]> = ref([]);
+// 团队成员
+let teamList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string };
+  await searchUnit();
+  await searchOther();
+  await search();
+});
+// 查询依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async () => {
+  let data: any = {
+    user_id: user.value._id,
+    company_id: unitInfo.value._id,
+    company_name: unitInfo.value.company,
+    zy_fields: [],
+    hz_fields: [],
+    team: [],
+    hz_direction: [],
+    settle_file: [],
+    build_file: [],
+    status: '0',
+  };
+  if (route.query && route.query.id) {
+    let id = route.query.id;
+    const res: any = await studio.fetch(id);
+    if (res.errcode == 0) {
+      if (res.data) {
+        res.data.team = await sarchTeam();
+        form.value = res.data as { scientist_id: ''; scientistinfo_id: ''; scientist_name: ''; team: [] };
+      }
+    }
+  } else {
+    form.value = { ...data };
+  }
+  // 状态判断显示
+  if (route.query && route.query.status == '0') active.value = 3;
+  else if (route.query && route.query.status == '1') active.value = 4;
+};
+// 查询团队信息
+const sarchTeam = async () => {
+  let list = [];
+  const res: any = await scientistsettle.query({ studio_id: route.query.id });
+  if (res.errcode == 0) {
+    if (res.total > 0) {
+      let data = res.data[0];
+      list = data.team;
+    }
+  }
+  return list;
+};
+const toStep = (e: number) => {
+  active.value = e;
+};
+// 查询科学家信息
+const searchSci = async (name: string) => {
+  let res = await userStudioApply.query({ name: name });
+  if (res.errcode == 0) {
+    for (const val of res.data as any[]) {
+      let arr: any = await users.fetch(val.user_id);
+      if (arr.errcode == 0) {
+        if (arr.data && arr.data.card) val.card = arr.data.card;
+        else val.card = '暂无';
+      }
+    }
+    sciInfoList.value = res.data as any[];
+  }
+};
+// 选择科学家
+const scChange = (e: string) => {
+  let data = sciInfoList.value.find((i) => i._id == e);
+  if (data) {
+    form.value.scientist_id = data.user_id;
+    form.value.scientistinfo_id = data._id;
+    form.value.scientist_name = data.name;
+  }
+};
+// 提交
+const toSubmit = async () => {
+  teamList.value = form.value.team;
+  let data: any = form.value;
+  delete data.team;
+  data.status = '0';
+  let res: IQueryResult;
+  if (data._id) res = await studio.update(data);
+  else {
+    res = await studio.create(data);
+    // 创建入驻信息
+    createSettle(data, res.data);
+  }
+  if (res.errcode == 0) {
+    ElMessage({ type: 'success', message: '维护申报材料提交成功信息成功' });
+    toBack();
+  } else ElMessage({ type: 'warning', message: `${res.errmsg}` });
+};
+// 创建入驻信息
+const createSettle = async (e, studio) => {
+  let data = sciInfoList.value.find((i) => i._id == e.scientistinfo_id);
+  let form = {
+    user_id: data.user_id,
+    scientist_id: data._id,
+    scientist_name: data.name,
+    company: data.company,
+    zc: data.zc,
+    fields: data.fields,
+    direction: data.direction,
+    company_id: e.company_id,
+    company_name: e.company_name,
+    settle_file: e.settle_file,
+    team: teamList.value,
+    studio_id: studio._id,
+  };
+  let res = await scientistsettle.create(form);
+  console.log(res);
+};
+// 返回
+const toBack = () => {
+  window.history.go(-1);
+};
+// 查询其他信息
+const searchOther = async () => {
+  // 领域
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_field' });
+  fieldList.value = p1.data as [];
+};
+</script>
 
-<style scoped></style>
+<style lang="scss" scoped>
+.main {
+  .two {
+    .two_1 {
+      margin: 0 0 10px 0;
+    }
+  }
+}
+</style>

+ 142 - 7
src/views/unit/studio/index.vue

@@ -1,11 +1,146 @@
 <template>
   <div id="index">
-    <el-row>
-      <el-col :span="24" class="main"> test </el-col>
-    </el-row>
+    <el-col class="main animate__animated animate__backInRight">
+      <el-col :span="24" class="one">
+        <component :is="partsSearch" :is_search="true" :fields="fields" @search="partSearch">
+          <template #status>
+            <el-option v-for="i in statusList" :key="i.dict_value" :label="i.dict_label" :value="i.dict_value"></el-option>
+          </template>
+        </component>
+      </el-col>
+      <el-col :span="24" class="two">
+        <component :is="Btn1" @toAdd="toAdd"></component>
+      </el-col>
+      <el-col :span="24" class="thr">
+        <component
+          :is="CTable"
+          :fields="fields"
+          :opera="opera"
+          :select="false"
+          :selected="selected"
+          @handleSelect="handleSelect"
+          @query="search"
+          :data="tableData"
+          :total="total"
+          @view="toView"
+        >
+        </component>
+      </el-col>
+    </el-col>
   </div>
 </template>
-
-<script setup lang="ts"></script>
-
-<style scoped></style>
+<script setup lang="ts">
+import store from '@/stores/counter';
+import { ElMessage } from 'element-plus';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CTable from '@/components/c-table.vue';
+import Btn1 from '@/components/btn-1.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+// #region 接口
+import { StudioStore } from '@common/src/stores/studio/studios/studio'; // 工作室
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import type { IQueryResult } from '@/util/types.util';
+const studio = StudioStore();
+const unitStudioApply = UnitStudioApplyStore();
+const sysdictdata = DictDataStore();
+const { proxy } = getCurrentInstance() as any;
+const router = useRouter();
+// #endregion
+// 列表数据
+let tableData: Ref<any[]> = ref([]);
+// 总数
+let total: Ref<number> = ref(0);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '序号', options: { type: 'index' } },
+  { label: '工作室名称', model: 'name', isSearch: true },
+  { label: '依托单位', model: 'company_name', isSearch: true },
+  { label: '入驻科学家', model: 'scientist_name', isSearch: true },
+  { label: '申报日期', model: 'apply_time' },
+  {
+    label: '申报状态',
+    model: 'status',
+    type: 'select',
+    format: (i) => {
+      let data = statusList.value.find((r) => r.dict_value == i);
+      if (data) return data.dict_label;
+    },
+    isSearch: true,
+  },
+]);
+// 操作
+let opera: Ref<any[]> = ref([{ label: '申报进度', method: 'view' }]);
+// 多选
+let selected: Ref<any[]> = ref([]);
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 查询数据
+let searchForm: Ref<{}> = ref({});
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String }> = ref({ _id: '', status: '' });
+// 状态
+let statusList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search({ skip, limit });
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    const { skip, limit } = e;
+    let info = { limit: limit, skip: skip, ...searchForm.value, company_id: unitInfo.value._id };
+    const res: IQueryResult = await studio.query(info);
+    tableData.value = res.data as any[];
+    total.value = res.total;
+  } else {
+    ElMessage({ type: 'warning', message: `用户未完成信息填报/信息填报未完成审核,无法查询相关信息` });
+  }
+};
+// 查询
+const partSearch = (form: { [x: string]: any }) => {
+  searchForm.value = form;
+  search({ skip, limit });
+};
+// 添加
+const toAdd = () => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    router.push({ path: '/unit/studio/add' });
+  } else {
+    ElMessage({ message: '用户未完成信息填报/信息填报未完成审核,无法查询相关信息', type: 'warning' });
+  }
+};
+// 申报进度
+const toView = (data: { _id: string; status: string }) => {
+  router.push({ path: '/unit/studio/add', query: { id: data._id, status: data.status } });
+};
+// 选择
+const handleSelect = () => {};
+// 查询其他信息
+const searchOther = async () => {
+  // 审核状态
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_studio_status', is_use: '0' });
+  statusList.value = p1.data as [];
+};
+</script>
+<style lang="scss" scoped>
+.main {
+  .thr {
+    margin: 1vw 0 0 0;
+  }
+}
+</style>

+ 76 - 0
src/views/unit/studio/parts/form-1.vue

@@ -0,0 +1,76 @@
+<template>
+  <div id="form-1">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="auto">
+          <el-form-item label="依托单位名称" prop="company_name">
+            <el-input v-model="form.company_name" placeholder="请输入依托单位名称"></el-input>
+          </el-form-item>
+          <el-form-item label="专业领域" prop="zy_fields">
+            <el-select v-model="form.zy_fields" multiple placeholder="请选择专业领域" clearable filterable style="width: 100%">
+              <el-option v-for="item in fieldList" :key="item._id" :label="item.dict_label" :value="item.dict_value"> </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="申报日期" prop="apply_time">
+            <el-date-picker
+              v-model="form.apply_time"
+              type="datetime"
+              format="YYYY-MM-DD HH:mm:ss"
+              value-format="YYYY-MM-DD HH:mm:ss"
+              placeholder="请选择申报日期"
+              style="width: 100%"
+            />
+          </el-form-item>
+          <el-col :span="24" class="btn">
+            <el-button type="success" size="small" @click="toStep(ruleFormRef, 1)">下一步</el-button>
+          </el-col>
+        </el-form>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, toRefs, reactive } from 'vue';
+import type { FormInstance, FormRules } from 'element-plus';
+interface FieldItem {
+  _id: string;
+  dict_label: string;
+  dict_value: string;
+}
+// 传入参数
+const props = defineProps({
+  form: { type: Object, default: () => {} },
+  fieldList: { type: Array<FieldItem> },
+});
+const { form } = toRefs(props);
+const { fieldList } = toRefs(props);
+const ruleFormRef = ref<FormInstance>();
+const emit = defineEmits(['toStep']);
+// 必填项
+const rules = reactive<FormRules>({
+  company_name: [{ required: true, message: '请输入依托单位名称', trigger: 'blur' }],
+  zy_fields: [{ required: true, message: '请选择专业领域', trigger: 'change' }],
+  apply_time: [{ required: true, message: '请选择申报日期', trigger: 'change' }],
+});
+// 下一步
+const toStep = (formEl: FormInstance | undefined, e: number) => {
+  if (!formEl) return;
+  formEl.validate((valid) => {
+    if (valid) {
+      emit('toStep', e);
+    } else {
+      console.log('error submit!');
+      return false;
+    }
+  });
+};
+</script>
+
+<style lang="scss" scoped>
+.main {
+  .btn {
+    text-align: center;
+  }
+}
+</style>

+ 219 - 0
src/views/unit/studio/parts/form-2.vue

@@ -0,0 +1,219 @@
+<template>
+  <div id="form-2">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="130px">
+          <el-form-item label="工作室名称" prop="name">
+            <el-input v-model="form.name" placeholder="请输入工作室名称"></el-input>
+          </el-form-item>
+          <el-form-item label="入驻科学家" prop="scientistinfo_id">
+            <el-select
+              v-model="form.scientistinfo_id"
+              clearable
+              filterable
+              remote
+              reserve-keyword
+              placeholder="请输入科学家名称"
+              :remote-method="remoteMethod"
+              :loading="loading"
+              style="width: 100%"
+              @change="scChange"
+            >
+              <el-option v-for="item in sciInfoList" :key="item._id" :label="`${item.name}(${item.card})`" :value="item._id"> </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="团队成员" prop="team">
+            <el-col :span="24">
+              <el-button type="primary" size="small" @click="addTeam()">添加团队成员</el-button>
+              <el-col :span="24" class="team_txt">
+                <p>注意:<span>1.团队成员人数不可超过15人!</span><span>2.录入科学家团队成员(由科学家提供)</span></p>
+              </el-col>
+            </el-col>
+            <el-col :span="24">
+              <el-table :data="form.team" border size="small">
+                <el-table-column type="index" label="序号" width="50" align="center"> </el-table-column>
+                <el-table-column prop="name" label="姓名" align="center">
+                  <template v-slot="scope">
+                    <el-input v-model="scope.row.name" placeholder="请输入姓名"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="company" label="工作单位" align="center">
+                  <template v-slot="scope">
+                    <el-input v-model="scope.row.company" placeholder="请输入工作单位"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="zc" label="职称" align="center">
+                  <template v-slot="scope">
+                    <el-input v-model="scope.row.zc" placeholder="请输入职称"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="phone" label="手机号码" align="center">
+                  <template v-slot="scope">
+                    <el-input v-model="scope.row.phone" placeholder="请输入手机号码"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" width="100" v-if="form.status == null">
+                  <template v-slot="scope">
+                    <el-button size="small" type="danger" @click="delTeam(scope.row)">删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-col>
+          </el-form-item>
+          <el-form-item label="合作领域" prop="hz_fields">
+            <el-select v-model="form.hz_fields" multiple placeholder="请选择合作领域" clearable filterable style="width: 100%">
+              <el-option v-for="item in fieldList" :key="item._id" :label="item.dict_label" :value="item.dict_value"> </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="合作方向" prop="hz_direction">
+            <el-button style="margin-bottom: 0.5vw" type="primary" size="small" @click="addDriection()">添加</el-button>
+            <el-col :span="24">
+              <el-table :data="form.hz_direction" border size="small">
+                <el-table-column type="index" label="序号" width="50" align="center"> </el-table-column>
+                <el-table-column prop="name" label="名称" align="center">
+                  <template v-slot="scope">
+                    <el-input v-model="scope.row.name" placeholder="请输入技术合作方向名称"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" width="100">
+                  <template v-slot="scope">
+                    <el-button size="small" type="danger" @click="delDriection(scope.row)">删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-col>
+          </el-form-item>
+          <el-form-item label="入驻协议" prop="settle_file">
+            <component :is="CFile" model="settle_file" :limit="limit" :url="url" :list="form.settle_file" @change="onChange"></component>
+          </el-form-item>
+          <el-form-item label="科学家所在单位同意入驻证明材料" prop="unit_settle_file">
+            <component :is="CFile" model="unit_settle_file" :limit="limit" :url="url" :list="form.unit_settle_file" @change="onChange"></component>
+          </el-form-item>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" size="small" @click="toStep(ruleFormRef, 0)">上一步</el-button>
+            <el-button type="success" size="small" @click="toStep(ruleFormRef, 2)">下一步</el-button>
+          </el-col>
+        </el-form>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// #region 组件
+import CFile from '@/components/c-upload.vue';
+// #endregion
+import moment from 'moment';
+import type { Ref } from 'vue';
+import { ref, toRefs, reactive } from 'vue';
+import { ElMessage } from 'element-plus';
+import type { FormInstance, FormRules } from 'element-plus';
+interface FieldItem {
+  _id: string;
+  dict_label: string;
+  dict_value: string;
+}
+interface sciInfoItem {
+  _id: string;
+  name: string;
+  card: string;
+}
+// 传入参数
+const props = defineProps({
+  form: { type: Object, default: () => {} },
+  fieldList: { type: Array<FieldItem> },
+  sciInfoList: { type: Array<sciInfoItem> },
+});
+const { form } = toRefs(props);
+const { fieldList } = toRefs(props);
+const ruleFormRef = ref<FormInstance>();
+const emit = defineEmits(['toStep', 'scChange', 'searchSci']);
+// 必填项
+const rules = reactive<FormRules>({
+  name: [{ required: true, message: '请输入工作室名称', trigger: 'blur' }],
+  scientistinfo_id: [{ required: true, message: '请选择入驻科学家', trigger: 'change' }],
+  team: [{ required: false, message: '请添加团队成员', trigger: 'change' }],
+  hz_fields: [{ required: true, message: '请选择合作领域', trigger: 'change' }],
+  hz_direction: [{ required: true, message: '请添加合作方向', trigger: 'change' }],
+  settle_file: [{ required: true, message: '请上传入驻协议', trigger: 'change' }],
+  unit_settle_file: [{ required: true, message: '请上传科学家所在单位同意入驻证明材料', trigger: 'change' }],
+});
+let limit: Ref<number> = ref(1);
+let url: Ref<string> = ref('/files/studioadmin/studio/upload');
+let loading: Ref<boolean> = ref(false);
+// 下一步
+const toStep = (formEl: FormInstance | undefined, e: number) => {
+  if (!formEl) return;
+  if (e == 0) {
+    emit('toStep', e);
+  } else {
+    formEl.validate((valid) => {
+      if (valid) {
+        emit('toStep', e);
+      } else {
+        console.log('error submit!');
+        return false;
+      }
+    });
+  }
+};
+// 上传
+const onChange = (e: { model: string; value: Array<[]> }) => {
+  const { model, value } = e;
+  form.value[model] = value;
+};
+// 改变科学家名称
+const scChange = (e) => {
+  emit('scChange', e);
+};
+// 技术合作方向添加
+const addDriection = () => {
+  let hz_direction = form.value.hz_direction;
+  if (hz_direction.length >= 5) {
+    ElMessage({ message: `技术合作方向最多添加五个`, type: 'error' });
+  } else {
+    hz_direction.push({ id: moment().valueOf(), name: '' });
+  }
+  form.value.hz_direction = hz_direction;
+};
+// 研究方向删除
+const delDriection = (e) => {
+  let direction = form.value.direction.filter((i: any) => i.id != e.id);
+  form.value.direction = direction;
+};
+// 添加成员信息
+const addTeam = () => {
+  let team = form.value.team;
+  if (team.length >= 15) {
+    ElMessage({ message: `团队成员人数不可超过15人!`, type: 'error' });
+  } else {
+    team.push({ id: moment().valueOf(), name: '' });
+  }
+  form.value.team = team;
+};
+// 团队成员信息删除
+const delTeam = (e) => {
+  let team = form.value.team.filter((i: any) => i.id != e.id);
+  form.value.team = team;
+};
+// 查询科学家
+const remoteMethod = (query) => {
+  loading.value = true;
+  emit('searchSci', query);
+  loading.value = false;
+};
+</script>
+
+<style lang="scss" scoped>
+.main {
+  .btn {
+    text-align: center;
+  }
+}
+.team_txt {
+  font-size: 14;
+  span {
+    color: #ff0000;
+  }
+}
+</style>

+ 67 - 0
src/views/unit/studio/parts/form-3.vue

@@ -0,0 +1,67 @@
+<template>
+  <div id="form-3">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="auto">
+          <el-form-item label="工作室建设方案" prop="build_file">
+            <component :is="CFile" model="build_file" :limit="limit" :url="url" :list="form.build_file" @change="onChange"></component>
+          </el-form-item>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" size="small" @click="toStep(1)">上一步</el-button>
+            <el-button type="success" size="small" @click="toSubmit(ruleFormRef)">提交申报</el-button>
+          </el-col>
+        </el-form>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// #region 组件
+import CFile from '@/components/c-upload.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, toRefs, reactive } from 'vue';
+import type { FormInstance, FormRules } from 'element-plus';
+// 传入参数
+const props = defineProps({
+  form: { type: Object, default: () => {} },
+});
+const { form } = toRefs(props);
+const ruleFormRef = ref<FormInstance>();
+const emit = defineEmits(['toStep', 'toSubmit']);
+// 必填项
+const rules = reactive<FormRules>({
+  build_file: [{ required: true, message: '请上传工作室建设方案', trigger: 'change' }],
+});
+let limit: Ref<number> = ref(1);
+let url: Ref<string> = ref('/files/studioadmin/studio/upload');
+// 下一步
+const toStep = (e: number) => {
+  emit('toStep', e);
+};
+// 上传
+const onChange = (e: { model: string; value: Array<[]> }) => {
+  const { model, value } = e;
+  form.value[model] = value;
+};
+// 提交
+const toSubmit = (formEl: FormInstance | undefined) => {
+  formEl.validate((valid) => {
+    if (valid) {
+      emit('toSubmit');
+    } else {
+      console.log('error submit!');
+      return false;
+    }
+  });
+};
+</script>
+
+<style lang="scss" scoped>
+.main {
+  .btn {
+    text-align: center;
+  }
+}
+</style>

+ 123 - 3
src/views/unit/yearreport/add.vue

@@ -1,11 +1,131 @@
 <template>
-  <div id="index">
+  <div id="add">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_back="true" @toBack="toBack"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="CForm" :fields="fields" :rules="rules" :form="form" @dataChange="dataChange" labelWidth="auto" @save="toSave">
+            <template #studio_id>
+              <el-option v-for="i in studioList" :key="i._id" :label="i.name" :value="i._id"></el-option>
+            </template>
+            <template #file>
+              <component :is="CFile" model="file" :limit="limit" :url="url" :list="form.file" @change="onChange"></component>
+            </template>
+          </component>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import store from '@/stores/counter';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CForm from '@/components/c-form.vue';
+import CFile from '@/components/c-upload.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, reactive } from 'vue';
+import type { FormRules } from 'element-plus';
+import { ElMessage } from 'element-plus';
+import { useRoute } from 'vue-router';
+// #region 接口
+import { YearreportStore } from '@common/src/stores/studio/studios/yearreport'; //年度报告
+import { StudioStore } from '@common/src/stores/studio/studios/studio'; // 工作室
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; //个人账号申请科学家工作室权限表
+import type { IQueryResult } from '@/util/types.util';
+const yearreport = YearreportStore();
+const studio = StudioStore();
+const unitStudioApply = UnitStudioApplyStore();
+let route = useRoute();
+// 必填项
+const rules = reactive<FormRules>({
+  studio_id: [{ required: true, message: '请选择工作室名称', trigger: 'change' }],
+  file: [{ required: true, message: '请上传报告文件', trigger: 'change' }],
+  apply_time: [{ required: true, message: '请选择申请时间', trigger: 'change' }],
+});
+// 表单
+let fields: Ref<any[]> = ref([
+  { label: '依托单位名称', model: 'company_name', options: { readonly: true } },
+  { label: '工作室名称', model: 'studio_id', type: 'select' },
+  { label: '报告文件', model: 'file', custom: true },
+  { label: '申请时间', model: 'apply_time', type: 'date' },
+]);
+let limit: Ref<number> = ref(1);
+let url: Ref<string> = ref('/files/studioadmin/yearreport/upload');
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String; company: string; phone: string }> = ref({ _id: '', status: '', company: '', phone: '' });
+// 表单
+let form: Ref<{ file: Array<[]>; studio_name: string }> = ref({ file: [], studio_name: '' });
+// 工作室列表
+let studioList: Ref<any[]> = ref([]);
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search();
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async () => {
+  let data = {
+    user_id: unitInfo.value._id,
+    company_name: unitInfo.value.company,
+    file: [],
+    studio_name: '',
+  };
+  if (route.query && route.query.id) {
+    let id = route.query.id;
+    const res: IQueryResult = await yearreport.fetch(id);
+    if (res.errcode == 0) {
+      if (res.data) form.value = res.data as { content: string; file: Array<[]>; studio_name: string };
+    }
+  } else {
+    form.value = { ...data };
+  }
+};
+// 返回
+const toBack = () => {
+  window.history.go(-1);
+};
+// 数据选择
+const dataChange = ({ model, value }) => {
+  if (model == 'studio_id') {
+    let data = studioList.value.find((i) => i.id == value);
+    if (data) form.value.studio_name = data.name;
+  }
+};
+// 上传
+const onChange = (e: { model: string; value: Array<[]> }) => {
+  const { model, value } = e;
+  form.value[model] = value;
+};
+// 添加
+const toSave = async (data: { _id: string }) => {
+  let res: IQueryResult;
+  if (data._id) res = await yearreport.update(data);
+  else res = await yearreport.create(data);
+  if (res.errcode == 0) {
+    ElMessage({ type: 'success', message: '维护信息成功' });
+    toBack();
+  } else ElMessage({ type: 'warning', message: `${res.errmsg}` });
+};
+// 查询其他信息
+const searchOther = async () => {
+  // 工作室
+  const p1: IQueryResult = await studio.query({ status: '7', user_id: user.value._id });
+  studioList.value = p1.data as [];
+};
+</script>
 
 <style scoped></style>

+ 153 - 4
src/views/unit/yearreport/index.vue

@@ -1,11 +1,160 @@
 <template>
   <div id="index">
     <el-row>
-      <el-col :span="24" class="main"> test </el-col>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="partsSearch" :is_search="true" :fields="fields" @search="partSearch">
+            <template #status>
+              <el-option v-for="i in statusList" :key="i.dict_value" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+          </component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="Btn1" @toAdd="toAdd"></component>
+        </el-col>
+        <el-col :span="24" class="thr">
+          <component
+            :is="CTable"
+            :fields="fields"
+            :opera="opera"
+            :select="false"
+            :selected="selected"
+            @handleSelect="handleSelect"
+            @query="search"
+            :data="tableData"
+            :total="total"
+            @edit="toEdit"
+            @del="toDel"
+          >
+          </component>
+        </el-col>
+      </el-col>
     </el-row>
   </div>
 </template>
+<script setup lang="ts">
+import store from '@/stores/counter';
+// #region 组件
+import partsSearch from '@/components/c-search.vue';
+import CTable from '@/components/c-table.vue';
+import Btn1 from '@/components/btn-1.vue';
+// #endregion
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { ElMessage } from 'element-plus';
+import { useRouter } from 'vue-router';
+// #region 接口
+import { YearreportStore } from '@common/src/stores/studio/studios/yearreport'; //年度报告
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import { UnitStudioApplyStore } from '@common/src/stores/studio/role/unitStudioApply'; // 依托单位申请科学家工作室权限表
+import type { IQueryResult } from '@/util/types.util';
+const yearreport = YearreportStore();
+const sysdictdata = DictDataStore();
+const unitStudioApply = UnitStudioApplyStore();
+const { proxy } = getCurrentInstance() as any;
+const router = useRouter();
+// #endregion
+// 列表数据
+let tableData: Ref<any[]> = ref([]);
+// 总数
+let total: Ref<number> = ref(0);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '序号', options: { type: 'index' } },
+  { label: '工作室名称', model: 'studio_name', isSearch: true },
+  { label: '依托单位名称', model: 'company_name' },
+  { label: '申请时间', model: 'apply_time' },
+  {
+    label: '审核状态',
+    model: 'status',
+    type: 'select',
+    format: (i) => {
+      let data = statusList.value.find((r) => r.dict_value == i);
+      if (data) return data.dict_label;
+    },
+    isSearch: true,
+  },
+]);
+// 操作
+let opera: Ref<any[]> = ref([
+  { label: '修改', method: 'edit', type: 'warning', display: (i) => i.status == '0' },
+  { label: '删除', method: 'del', type: 'danger', confirm: true },
+]);
+// 多选
+let selected: Ref<any[]> = ref([]);
+// 用户信息
+let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
+// 依托单位信息
+let unitInfo: Ref<{ _id: String; status: String }> = ref({ _id: '', status: '' });
+// 查询数据
+let searchForm: Ref<{}> = ref({});
+// 状态
+let statusList: Ref<any[]> = ref([]);
 
-<script setup lang="ts"></script>
-
-<style scoped></style>
+onMounted(async () => {
+  user.value = store.state.user as { _id: string; name: string; unit_name: string; nick_name: string };
+  await searchUnit();
+  await searchOther();
+  await search({ skip, limit });
+});
+// 依托单位信息
+const searchUnit = async () => {
+  const res: IQueryResult = await unitStudioApply.query({ unit_id: user.value._id });
+  let list = res.data as any[];
+  if (res.total > 0) unitInfo.value = list[0];
+};
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    const { skip, limit } = e;
+    let info = { limit: limit, skip: skip, ...searchForm.value, company_id: unitInfo.value._id };
+    const res: IQueryResult = await yearreport.query(info);
+    tableData.value = res.data as any[];
+    total.value = res.total;
+  } else {
+    ElMessage({ type: 'warning', message: `用户未完成信息填报/信息填报未完成审核,无法查询相关信息` });
+  }
+};
+// 查询
+const partSearch = (form: { [x: string]: any }) => {
+  searchForm.value = form;
+  search({ skip, limit });
+};
+// 添加
+const toAdd = () => {
+  if (unitInfo && unitInfo.value._id && unitInfo.value.status == '1') {
+    router.push({ path: '/unit/yearreport/add' });
+  } else {
+    ElMessage({ message: '用户未完成信息填报/信息填报未完成审核,无法查询相关信息', type: 'warning' });
+  }
+};
+// 修改
+const toEdit = (data: { _id: string }) => {
+  router.push({ path: '/unit/yearreport/add', query: { id: data._id } });
+};
+// 删除
+const toDel = async (data: { _id: string }) => {
+  const res: IQueryResult = await yearreport.del(data._id);
+  if (res.errcode == 0) {
+    ElMessage({ message: '删除信息成功', type: 'success' });
+    search({ skip, limit });
+  }
+};
+// 选择
+const handleSelect = () => {};
+// 查询其他信息
+const searchOther = async () => {
+  // 字典表---审核状态
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_status', is_use: '0' });
+  statusList.value = p1.data as [];
+};
+</script>
+<style lang="scss" scoped>
+.main {
+  .thr {
+    margin: 1vw 0 0 0;
+  }
+}
+</style>

+ 2 - 0
src/views/user/scientist/studio/index.vue

@@ -108,11 +108,13 @@ onMounted(async () => {
   await search({ skip, limit });
   await searchStudio();
 });
+// 查询个人用户信息
 const searchUser = async () => {
   const res: IQueryResult = await userStudioApply.query({ user_id: user.value._id });
   let list = res.data as any[];
   if (res.total > 0) userInfo.value = list[0];
 };
+// 查询工作室信息
 const searchStudio = async () => {
   const res: IQueryResult = await scientistsettle.query({ scientist_id: userInfo.value._id });
   let studio = res.data as any[];

+ 2 - 0
src/views/user/scientist/studio/info.vue

@@ -28,6 +28,7 @@ let info: Ref<{ team: Array<[]> }> = ref({ team: [] });
 onMounted(async () => {
   await search();
 });
+// 查询
 const search = async () => {
   if (route.query && route.query.id) {
     let id = route.query.id;
@@ -39,6 +40,7 @@ const search = async () => {
     }
   }
 };
+// 返回
 const toBack = () => {
   window.history.go(-1);
 };

+ 6 - 6
src/views/user/support/add.vue

@@ -48,7 +48,6 @@ const techolsupport = TecholsupportStore();
 const sysdictdata = DictDataStore();
 const userStudioApply = UserStudioApplyStore();
 let route = useRoute();
-interface dataItem {}
 // 必填项
 const rules = reactive<FormRules>({
   scientist_name: [{ required: true, message: '请输入科学家姓名', trigger: 'blur' }],
@@ -73,7 +72,7 @@ let fields: Ref<any[]> = ref([
   { label: '是否启用', model: 'is_use', type: 'select' },
 ]);
 let limit: Ref<number> = ref(1);
-let url: Ref<string> = ref('/files/studioadmin/other/upload');
+let url: Ref<string> = ref('/files/studioadmin/support/upload');
 // 用户信息
 let user: Ref<{ _id: string; name: string; unit_name: string; nick_name: string }> = ref({ _id: '', name: '', unit_name: '', nick_name: '' });
 // 个人用户信息
@@ -86,7 +85,7 @@ let userInfo: Ref<{ name: string; _id: String; user_id: String; status: String;
   phone: { phone: '' },
 });
 // 表单
-let form: Ref<{ content: string; file: dataItem[] }> = ref({ content: '', file: [] });
+let form: Ref<{ content: string; file: Array<[]> }> = ref({ content: '', file: [] });
 // 行业领域
 let fieldList: Ref<any[]> = ref([]);
 // 是否启用
@@ -97,6 +96,7 @@ onMounted(async () => {
   await searchUser();
   await search();
 });
+ // 查询个人用户信息
 const searchUser = async () => {
   const res: IQueryResult = await userStudioApply.query({ user_id: user.value._id });
   let list = res.data as any[];
@@ -116,7 +116,7 @@ const search = async () => {
     let id = route.query.id;
     const res: IQueryResult = await techolsupport.fetch(id);
     if (res.errcode == 0) {
-      if (res.data) form.value = res.data as { content: string; file: dataItem[] };
+      if (res.data) form.value = res.data as { content: string; file: Array<[]> };
     }
   } else {
     form.value = { ...data };
@@ -127,7 +127,7 @@ const toBack = () => {
   window.history.go(-1);
 };
 // 上传
-const onChange = (e: { model: string; value: Array<dataItem> }) => {
+const onChange = (e: { model: string; value: Array<[]> }) => {
   const { model, value } = e;
   form.value[model] = value;
 };
@@ -143,7 +143,7 @@ const toSave = async (data: { _id: string }) => {
 };
 // 查询其他信息
 const searchOther = async () => {
-  // 字典表---审核状态
+  // 领域
   const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_field' });
   fieldList.value = p1.data as [];
   // 角色

+ 2 - 1
src/views/user/support/index.vue

@@ -111,6 +111,7 @@ onMounted(async () => {
   await searchOther();
   await search({ skip, limit });
 });
+// 查询个人用户信息
 const searchUser = async () => {
   const res: IQueryResult = await userStudioApply.query({ user_id: user.value._id });
   let list = res.data as any[];
@@ -171,7 +172,7 @@ const handleSelect = () => {};
 // 查询其他信息
 const searchOther = async () => {
   // 字典表---审核状态
-  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_status' });
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'studio_status', is_use: '0' });
   statusList.value = p1.data as [];
   // 角色
   const p2: IQueryResult = await sysdictdata.query({ dict_type: 'sys_yes_no' });

+ 2 - 0
src/views/user/support/info.vue

@@ -26,6 +26,7 @@ let info: Ref<{}> = ref({});
 onMounted(async () => {
   await search();
 });
+// 查询
 const search = async () => {
   if (route.query && route.query.id) {
     let id = route.query.id;
@@ -33,6 +34,7 @@ const search = async () => {
     info.value = res.data as {};
   }
 };
+// 返回
 const toBack = () => {
   window.history.go(-1);
 };